diff --git a/project/app/wifi_app/wifi/librkwifibt.so b/project/app/wifi_app/wifi/librkwifibt.so index 2ae9821fa..1497aed27 100755 Binary files a/project/app/wifi_app/wifi/librkwifibt.so and b/project/app/wifi_app/wifi/librkwifibt.so differ diff --git a/project/build.sh b/project/build.sh index e91c6468d..94cf154c7 100755 --- a/project/build.sh +++ b/project/build.sh @@ -2321,7 +2321,7 @@ if [[ "$LF_TARGET_ROOTFS" = "ubuntu" ]]; then fi fi - if [ -d "$UBUNTU_DIR" ] && [ -f ${UBUNTU_DIR}/luckfox-ubuntu-22.04.3.tar.gz ]; then + if [ -d "$UBUNTU_DIR" ] && [ -f ${UBUNTU_DIR}/luckfox-ubuntu-22.04.3.tar.gz.md5 ]; then msg_info "${UBUNTU_DIR} is not empty, skipping submodule update!" else msg_info "${UBUNTU_DIR} is empty or does not exist, updateing submodule!" diff --git a/project/rkflash.sh b/project/rkflash.sh new file mode 100755 index 000000000..386abb3c3 --- /dev/null +++ b/project/rkflash.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +COMMON_DIR=$(cd "$(dirname "$(realpath "$0")")/.."; pwd) +SDK_DIR=$(realpath $COMMON_DIR) +UPGRADETOOL=$SDK_DIR/tools/linux/Linux_Upgrade_Tool/upgrade_tool +ROCKDEV_DIR=$SDK_DIR/output/image +LOADER=$ROCKDEV_DIR/download.bin +PARAMETER=$ROCKDEV_DIR/parameter.txt +UBOOT=$ROCKDEV_DIR/uboot.img +TRUST=$ROCKDEV_DIR/trust.img +BOOT=$ROCKDEV_DIR/boot.img +RECOVERY=$ROCKDEV_DIR/recovery.img +OEM=$ROCKDEV_DIR/oem.img +MISC=$ROCKDEV_DIR/misc.img +ROOTFS=$ROCKDEV_DIR/rootfs.img +USERDATA=$ROCKDEV_DIR/userdata.img +UPDATE=$ROCKDEV_DIR/update.img + +if [ ! -n "$1" ];then +echo "flash all images as default" +FLASH_TYPE=all +else +FLASH_TYPE="$1" +fi + +if [ $FLASH_TYPE = tb ] +then + $UPGRADETOOL ul -noreset $LOADER + $UPGRADETOOL di -p $PARAMETER + $UPGRADETOOL di -uboot $UBOOT + $UPGRADETOOL di -b $BOOT + $UPGRADETOOL rd +fi + +if [ $FLASH_TYPE = loader ] +then + if [ -n "$2" ];then + LOADER=$2 + fi + echo "flash loader: $LOADER" + $UPGRADETOOL ul $LOADER + exit 0 +fi + + +if [ $FLASH_TYPE = uboot ] +then + if [ -n "$2" ];then + UBOOT=$2 + fi + echo "flash uboot: $UBOOT" + $UPGRADETOOL di -uboot $UBOOT +fi + +if [ $FLASH_TYPE = boot ] +then + if [ -n "$2" ];then + BOOT=$2 + fi + echo "flash boot: $BOOT" + $UPGRADETOOL di -b $BOOT + $UPGRADETOOL rd + +fi + +if [ $FLASH_TYPE = oem ] +then + if [ -n "$2" ];then + OEM=$2 + fi + echo "flash oem: $OEM" + $UPGRADETOOL di -oem $OEM +fi + +if [ $FLASH_TYPE = userdata ] +then + if [ -n "$2" ];then + USERDATA=$2 + fi + echo "flash userdata: $USERDATA" + $UPGRADETOOL di -userdata $USERDATA +fi + +if [ $FLASH_TYPE = rootfs ] +then + if [ -n "$2" ];then + ROOTFS=$2 + fi + echo "flash rootfs: $ROOTFS" + $UPGRADETOOL di -rootfs $ROOTFS +fi + +if [ $FLASH_TYPE = update ] +then + $UPGRADETOOL uf $UPDATE +fi + +if [ $FLASH_TYPE = rd ] +then + $UPGRADETOOL rd +fi + +if [ $FLASH_TYPE = erase ] +then + $UPGRADETOOL EF $LOADER +fi + diff --git a/rkflash.sh b/rkflash.sh new file mode 120000 index 000000000..48905bfac --- /dev/null +++ b/rkflash.sh @@ -0,0 +1 @@ +project/rkflash.sh \ No newline at end of file diff --git a/sysdrv/Makefile b/sysdrv/Makefile index 99857c5a4..3c55a42fd 100644 --- a/sysdrv/Makefile +++ b/sysdrv/Makefile @@ -121,7 +121,7 @@ ifneq ($(findstring $(TARGET_ROOTFS),custom),) else ifneq ($(findstring $(TARGET_ROOTFS),alpine),) ROOTFS_BUILD_ENV := alpine else ifneq ($(findstring $(TARGET_ROOTFS),ubuntu),) - ROOTFS_BUILD_ENV := ubuntu + ROOTFS_BUILD_ENV := ubuntu drv else ifneq ($(findstring $(TARGET_ROOTFS),buildroot),) ROOTFS_BUILD_ENV := rootfs_prepare pctools buildroot boardtools drv else @@ -527,7 +527,7 @@ else cp -af $(BUSYBOX_DIR)/$(BUSYBOX_VER)/_install/* $(SYSDRV_DIR_OUT_ROOTFS) # luckfox - cp $(SYSDRV_DIR)/tools/board/android-tools/S90usb0config $(SYSDRV_DIR_OUT_ROOTFS)/etc/init.d + cp $(SYSDRV_DIR)/tools/board/android-tools/S99usb0config $(SYSDRV_DIR_OUT_ROOTFS)/etc/init.d touch $(SYSDRV_DIR_OUT_ROOTFS)/userdata/.busybox endif @@ -609,7 +609,7 @@ else cp $(SYSDRV_DIR)/tools/board/luckfox_config/S99luckfoxconfigload $(SYSDRV_DIR_OUT_ROOTFS)/etc/init.d/ cp $(SYSDRV_DIR)/tools/board/luckfox_config/luckfox-config $(SYSDRV_DIR_OUT_ROOTFS)/usr/bin/ cp $(SYSDRV_DIR)/tools/board/luckfox_config/luckfox_switch_rgb_resolution $(SYSDRV_DIR_OUT_ROOTFS)/usr/bin/ - cp $(SYSDRV_DIR)/tools/board/android-tools/S90usb0config $(SYSDRV_DIR_OUT_ROOTFS)/etc/init.d/ + cp $(SYSDRV_DIR)/tools/board/android-tools/S99usb0config $(SYSDRV_DIR_OUT_ROOTFS)/etc/init.d/ endif buildroot_clean: @@ -642,7 +642,6 @@ ifeq ($(ENABLE_EMMC),YES) cp $(SYSDRV_DIR)/tools/board/emmc/emmc_filesystem_resize.sh $(SYSDRV_DIR_OUT_ROOTFS)/usr/bin/filesystem_resize.sh cp $(SYSDRV_DIR)/tools/board/emmc/emmc_rc.local $(SYSDRV_DIR_OUT_ROOTFS)/etc/rc.local cp $(SYSDRV_DIR)/tools/board/emmc/emmc_wifi_bt_init.sh $(SYSDRV_DIR_OUT_ROOTFS)/usr/bin/wifi_bt_init.sh - cp $(SYSDRV_DIR)/tools/board/emmc/emmc_wifi_ko $(SYSDRV_DIR_OUT_ROOTFS)/usr/ko -r cp $(SYSDRV_DIR)/tools/board/emmc/udhcp/usr/bin/udhcpc $(SYSDRV_DIR_OUT_ROOTFS)/usr/bin/udhcpc cp $(SYSDRV_DIR)/tools/board/emmc/udhcp/usr/bin/udhcpd $(SYSDRV_DIR_OUT_ROOTFS)/usr/bin/udhcpd mkdir -p $(SYSDRV_DIR_OUT_ROOTFS)/usr/share/udhcpc diff --git a/sysdrv/drv_ko/wifi/aic8800dc/Kconfig b/sysdrv/drv_ko/wifi/aic8800dc/Kconfig index 8c91fdea6..c4c35219d 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/Kconfig +++ b/sysdrv/drv_ko/wifi/aic8800dc/Kconfig @@ -8,7 +8,8 @@ config AIC_FW_PATH depends on AIC_WLAN_SUPPORT string "Firmware & config file path" #default "/vendor/etc/firmware" - default "/lib/firmware/aic8800_sdio" + #default "/lib/firmware/aic8800_sdio" + default "/oem/usr/ko/aic8800dc_fw" help Path to the firmware & config file. diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/Makefile b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/Makefile index e1e4169bc..f58626f21 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/Makefile +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/Makefile @@ -1,10 +1,7 @@ -EXTRA_CFLAGS += -Wno-unused-function - CONFIG_SDIO_SUPPORT := y CONFIG_SDIO_PWRCTRL := y -# CONFIG_AIC_FW_PATH = "/vendor/etc/firmware" -# CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800dc_fw" CONFIG_AIC_FW_PATH = "/oem/usr/ko/aic8800dc_fw" +#CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800" export CONFIG_AIC_FW_PATH ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\" @@ -14,23 +11,32 @@ ccflags-y += -DAICWF_SDIO_SUPPORT ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL endif -CONFIG_GPIO_WAKEUP = n +CONFIG_GPIO_WAKEUP ?= n CONFIG_M2D_OTA_AUTO_SUPPORT = n CONFIG_M2D_OTA_LZMA_SUPPORT = n CONFIG_LINK_DET_5G = y CONFIG_MCU_MESSAGE = n CONFIG_FIRMWARE_ARRAY = n # Need to set fw path in BOARD_KERNEL_CMDLINE -CONFIG_USE_FW_REQUEST = n +CONFIG_USE_FW_REQUEST ?= n CONFIG_FDRV_NO_REG_SDIO = n CONFIG_VRF_DCDC_MODE = y -CONFIG_OOB = n +CONFIG_OOB ?= n CONFIG_PREALLOC_TXQ = y -CONFIG_ONE_TXQ = n CONFIG_DPD = y CONFIG_FORCE_DPD_CALIB = y -CONFIG_RESV_MEM_SUPPORT = y -CONFIG_AMSDU_RX ?=n +CONFIG_LOFT_CALIB = n +CONFIG_EXT_FEM_8800DCDW = n +CONFIG_RESV_MEM_SUPPORT ?= y +CONFIG_AMSDU_RX = n +CONFIG_IRQ_FALL ?= n +CONFIG_SDIO_BT = n + +ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) +CONFIG_DPD = n +CONFIG_FORCE_DPD_CALIB = n +CONFIG_LOFT_CALIB = y +endif ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP ccflags-$(CONFIG_M2D_OTA_AUTO_SUPPORT) += -DCONFIG_M2D_OTA_AUTO_SUPPORT @@ -43,11 +49,14 @@ ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE ccflags-$(CONFIG_OOB) += -DCONFIG_OOB ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ -ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD +ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB +ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ccflags-$(CONFIG_AMSDU_RX) += -DCONFIG_AMSDU_RX +ccflags-$(CONFIG_IRQ_FALL) += -DCONFIG_IRQ_FALL +ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT obj-m := $(MODULE_NAME).o $(MODULE_NAME)-y := \ @@ -65,7 +74,7 @@ ifeq ($(CONFIG_FIRMWARE_ARRAY),y) $(MODULE_NAME)-y += aicwf_firmware_array.o endif -# Platform support list +########## Platform support list ########## CONFIG_PLATFORM_ROCKCHIP ?= n CONFIG_PLATFORM_ROCKCHIP2 ?= n CONFIG_PLATFORM_ALLWINNER ?=n @@ -75,26 +84,6 @@ CONFIG_PLATFORM_UBUNTU ?= y ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP -#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/ -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- -#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel -#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel -#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel -#ARCH ?= arm64 -#CROSS_COMPILE ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/ -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel ARCH ?= arm64 CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- @@ -109,9 +98,6 @@ endif ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER -#KDIR ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/kernel/build/ -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/ ARCH ?= arm64 CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- @@ -140,7 +126,7 @@ MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ARCH ?= x86_64 CROSS_COMPILE ?= endif - +########################################### all: modules modules: diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800d80_compat.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800d80_compat.c index edc85f2b6..ae94ac146 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800d80_compat.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800d80_compat.c @@ -47,6 +47,14 @@ u32 adaptivity_patch_tbl_8800d80[][2] = { {0x0168, 0x00010000}, //tx_adaptivity_en }; +#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1) +#define USER_TX_USE_ANA_F_FLAG (0x01U << 2) + +#define CFG_USER_CHAN_MAX_TXPWR_EN 0 +#define CFG_USER_TX_USE_ANA_F 0 + +#define CFG_USER_EXT_FLAGS_EN (CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F) + u32 patch_tbl_8800d80[][2] = { #ifdef USE_5G {0x00b4, 0xf3010001}, @@ -56,9 +64,20 @@ u32 patch_tbl_8800d80[][2] = { #if defined(CONFIG_AMSDU_RX) {0x170, 0x0100000a} #endif -#if AIC_IRQ_WAKE_FLAG +#ifdef CONFIG_IRQ_FALL {0x00000170, 0x0000010a}, //irqf #endif + + #if CFG_USER_EXT_FLAGS_EN + {0x0188, 0x00000001 + #if CFG_USER_CHAN_MAX_TXPWR_EN + | USER_CHAN_MAX_TXPWR_EN_FLAG + #endif + #if CFG_USER_TX_USE_ANA_F + | USER_TX_USE_ANA_F_FLAG + #endif + }, // user_ext_flags + #endif }; #ifdef CONFIG_OOB @@ -90,11 +109,16 @@ int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev) return 0; } +#define NEW_PATCH_BUFFER_MAP 1 + int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev) { const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0198; u32 aic_patch_addr; u32 config_base, aic_patch_str_base; + #if (NEW_PATCH_BUFFER_MAP) + u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val; + #endif uint32_t start_addr = 0x0016F800; u32 patch_addr = start_addr; u32 patch_cnt = sizeof(patch_tbl_8800d80)/sizeof(u32)/2; @@ -126,6 +150,27 @@ int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev) } aic_patch_str_base = rd_patch_addr_cfm.memdata; + #if (NEW_PATCH_BUFFER_MAP) + rd_version_addr = RAM_FMAC_FW_ADDR + 0x01C; + if ((ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_version_addr, &rd_patch_addr_cfm))) { + printk("version val[0x%x] rd fail: %d\n", rd_version_addr, ret); + return ret; + } + rd_version_val = rd_patch_addr_cfm.memdata; + printk("rd_version_val=%08X\n", rd_version_val); + sdiodev->fw_version_uint = rd_version_val; + if (rd_version_val > 0x06090100) { + patch_buff_addr = rd_patch_addr + 12; + ret = rwnx_send_dbg_mem_read_req(sdiodev, patch_buff_addr, &rd_patch_addr_cfm); + if (ret) { + printk("patch buf rd fail\n"); + return ret; + } + patch_buff_base = rd_patch_addr_cfm.memdata; + patch_addr = start_addr = patch_buff_base; + } + #endif + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM); if (ret) { printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num)); diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.c index 2bbb087ba..15bb3d6de 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.c @@ -25,16 +25,18 @@ u32 syscfg_tbl_8800dc_sdio_u02[][2] = { {0x40030084, 0x0011E800}, {0x40030080, 0x00000001}, {0x4010001C, 0x00000000}, +}; #ifdef CONFIG_OOB - {0x40504044, 0x2},//oob_enable - {0x40500060, 0x03020700}, - {0x40500040, 0}, - {0x40100030, 1}, - {0x40241020, 1}, - {0x402400f0, 0x340022}, +u32 oobcfg_tbl_8800dc_sdio_u02[][2] = { + {0x40504044, 0x2},//oob_enable + {0x40500060, 0x03020700}, + {0x40500040, 0}, + {0x40100030, 1}, + {0x40241020, 1}, + {0x402400f0, 0x340022}, +}; #endif //CONFIG_OOB -}; u32 syscfg_tbl_masked_8800dc[][3] = { //#ifdef CONFIG_PMIC_SETTING @@ -1321,7 +1323,7 @@ uint32_t agc_cfg_ram[] = { 0x00000000 }; - +#if !defined(CONFIG_EXT_FEM_8800DCDW) uint32_t txgain_map[96] = { #ifdef CONFIG_FPGA_VERIFICATION 0x20c0c971, @@ -1459,8 +1461,8 @@ uint32_t txgain_map[96] = { 0x00ffc88b, 0x00ffc979, 0x00ffc989, - 0x00ffca7d, - 0x00ffca88, + 0x00ffcc4b, + 0x00ffcc54, 0x00ffcc5e, 0x00ffcc69, 0x00ffcc78, @@ -1492,8 +1494,8 @@ uint32_t txgain_map[96] = { 0x00ffc88b, 0x00ffc979, 0x00ffc989, - 0x00ffca7d, - 0x00ffca88, + 0x00ffcc4b, + 0x00ffcc54, 0x00ffcc5e, 0x00ffcc69, 0x00ffcc78, @@ -1501,9 +1503,9 @@ uint32_t txgain_map[96] = { 0x00ffcd70, 0x00ffcd80, 0x00ffcd90, - 0x00ffce80, - 0x00ffce93, - 0x00ffcf90, + 0x00ffcf68, + 0x00ffcf75, + 0x00ffcf83, 0x00ffc080, 0x00ffc090, 0x00ffc180, @@ -1562,8 +1564,8 @@ const uint32_t txgain_map_h[96] = 0xffc879, //8 0xffc96b, //9 0xffc979, //10 - 0xffca6b, //11 - 0xffca79, //12 + 0xffcc45, //11 + 0xffcc4d, //12 0xffcc56, //13 0xffcc60, //14 0xffcc6b, //15 @@ -1595,15 +1597,15 @@ const uint32_t txgain_map_h[96] = 0xffc879, //8 0xffc96b, //9 0xffc979, //10 - 0xffca6b, //11 - 0xffca79, //12 + 0xffcc45, //11 + 0xffcc4d, //12 0xffcc56, //13 0xffcc60, //14 0xffcc6b, //15 0xffcc79, //16 0xffcd72, //17 - 0xffce60, //18 - 0xffce72, //19 + 0xffcf5b, //18 + 0xffcf66, //19 0xffcf72, //20 0xffcf80, //21 0xffcf90, //22 @@ -1626,6 +1628,213 @@ const uint32_t txgain_map_h[96] = 0xffc86b, //7 }; +#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ +const uint32_t txgain_map_femkct[96] = +{ + //11b + 0x00ffd780,//15 + 0x00ffd872,//16 + 0x00ffd880,//17 + 0x00ffd972,//18 + 0x00ffd980,//19 + 0x00ffda72,//20 + 0x00ffda80,//21 + 0x00ffdb72,//22 + 0x00ffdb80,//23 + 0x00ffdc72,//24 + 0x00ffdc80,//25 + 0x00ffdd72,//26 + 0x00ffdd80,//27 + 0x00ffde72,//28 + 0x00ffde80,//29 + 0x00ffdf72,//30 + 0x00ffd072,//-1 + 0x00ffd072,//0 + 0x00ffd080,//1 + 0x00ffd172,//2 + 0x00ffd180,//3 + 0x00ffd272,//4 + 0x00ffd280,//5 + 0x00ffd36d,//6 + 0x00ffd379,//7 + 0x00ffd46d,//8 + 0x00ffd479,//9 + 0x00ffd572,//10 + 0x00ffd580,//11 + 0x00ffd672,//12 + 0x00ffd680,//13 + 0x00ffd772,//14 + //high + 0x00ffc872,//11 + 0x00ffc880,//12 + 0x00ffc972,//13 + 0x00ffc980,//14 + 0x00ffca72,//15 + 0x00ffca80,//16 + 0x00ffcb72,//17 + 0x00ffcb80,//18 + 0x00ffcc72,//19 + 0x00ffcc80,//20 + 0x00ffcd72,//21 + 0x00ffcd80,//22 + 0x00ffce72,//23 + 0x00ffce80,//24 + 0x00ffcf72,//25 + 0x00ffcf80,//26 + 0x00ffc072,//-5 + 0x00ffc080,//-4 + 0x00ffc172,//-3 + 0x00ffc180,//-2 + 0x00ffc272,//-1 + 0x00ffc280,//0 + 0x00ffc372,//1 + 0x00ffc380,//2 + 0x00ffc472,//3 + 0x00ffc480,//4 + 0x00ffc572,//5 + 0x00ffc580,//6 + 0x00ffc672,//7 + 0x00ffc680,//8 + 0x00ffc772,//9 + 0x00ffc780,//10 + //low + 0x00ffc872,//11 + 0x00ffc880,//12 + 0x00ffc972,//13 + 0x00ffc980,//14 + 0x00ffca72,//15 + 0x00ffca80,//16 + 0x00ffcb72,//17 + 0x00ffcb80,//18 + 0x00ffcc72,//19 + 0x00ffcc80,//20 + 0x00ffcd72,//21 + 0x00ffcd80,//22 + 0x00ffce72,//23 + 0x00ffce80,//24 + 0x00ffcf72,//26 + 0x00ffcf80,//27 + 0x00ffc072,//-5 + 0x00ffc080,//-4 + 0x00ffc172,//-3 + 0x00ffc180,//-2 + 0x00ffc272,//-1 + 0x00ffc280,//0 + 0x00ffc372,//1 + 0x00ffc380,//2 + 0x00ffc472,//3 + 0x00ffc480,//4 + 0x00ffc572,//5 + 0x00ffc580,//6 + 0x00ffc672,//7 + 0x00ffc680,//8 + 0x00ffc772,//9 + 0x00ffc780,//10 +}; + +const uint32_t txgain_map_femkct_h[96] = +{ + //11b + 0x00ffd872,//15 + 0x00ffd880,//16 + 0x00ffd972,//17 + 0x00ffd980,//18 + 0x00ffd990,//19 + 0x00ffda72,//20 + 0x00ffda80,//21 + 0x00ffdb72,//22 + 0x00ffdb80,//23 + 0x00ffdc72,//24 + 0x00ffdc80,//25 + 0x00ffdd72,//26 + 0x00ffdd80,//27 + 0x00ffde72,//28 + 0x00ffde80,//29 + 0x00ffdf72,//30 + 0x00ffd072,//-1 + 0x00ffd072,//0 + 0x00ffd080,//1 + 0x00ffd172,//2 + 0x00ffd180,//3 + 0x00ffd272,//4 + 0x00ffd280,//5 + 0x00ffd379,//6 + 0x00ffd46d,//7 + 0x00ffd479,//8 + 0x00ffd572,//9 + 0x00ffd580,//10 + 0x00ffd672,//11 + 0x00ffd680,//12 + 0x00ffd772,//13 + 0x00ffd780,//14 + //high + 0x00ffc880,//11 + 0x00ffc972,//12 + 0x00ffc980,//13 + 0x00ffca72,//14 + 0x00ffca80,//15 + 0x00ffcb72,//16 + 0x00ffcb80,//17 + 0x00ffcc72,//18 + 0x00ffcc80,//19 + 0x00ffcc90,//20 + 0x00ffcd72,//21 + 0x00ffcd80,//22 + 0x00ffce72,//23 + 0x00ffce80,//24 + 0x00ffcf72,//25 + 0x00ffcf80,//26 + 0x00ffc080,//-5 + 0x00ffc172,//-4 + 0x00ffc180,//-3 + 0x00ffc272,//-2 + 0x00ffc280,//-1 + 0x00ffc372,//0 + 0x00ffc380,//1 + 0x00ffc472,//2 + 0x00ffc480,//3 + 0x00ffc572,//4 + 0x00ffc580,//5 + 0x00ffc672,//6 + 0x00ffc680,//7 + 0x00ffc772,//8 + 0x00ffc780,//9 + 0x00ffc872,//10 + //low + 0x00ffc880,//11 + 0x00ffc972,//12 + 0x00ffc980,//13 + 0x00ffca72,//14 + 0x00ffca80,//15 + 0x00ffcb72,//16 + 0x00ffcb80,//17 + 0x00ffcc72,//18 + 0x00ffcc80,//19 + 0x00ffcc90,//20 + 0x00ffcd72,//21 + 0x00ffcd80,//22 + 0x00ffce72,//23 + 0x00ffce80,//24 + 0x00ffcf72,//25 + 0x00ffcf80,//26 + 0x00ffc080,//-5 + 0x00ffc172,//-4 + 0x00ffc180,//-3 + 0x00ffc272,//-2 + 0x00ffc280,//-1 + 0x00ffc372,//0 + 0x00ffc380,//1 + 0x00ffc472,//2 + 0x00ffc480,//3 + 0x00ffc572,//4 + 0x00ffc580,//5 + 0x00ffc672,//6 + 0x00ffc680,//7 + 0x00ffc772,//8 + 0x00ffc780,//9 + 0x00ffc872,//10 +}; +#endif u32 jump_tbl[][2] = { @@ -1687,10 +1896,61 @@ u32 patch_tbl_rf_func[][2] = {0x00110bf0, 0x00180001}, }; + +//adap test +u32 adaptivity_patch_tbl_8800dc[][2] = { + {0x000C, 0x0000320A}, //linkloss_thd + {0x009C, 0x00000000}, //ac_param_conf + {0x0128, 0xF6140001}, //tx_adaptivity_en +}; +//adap test + + static u8 chip_id = 0; #define CHIP_ID_H_MASK 0xC0 #define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK) +//Crystal provided by CPU (start) +int set_bbpll_config(struct aic_sdio_dev *rwnx_hw){ +// {0x40505010, 0x7C301010},//bbpll + int ret = 0; + struct dbg_mem_read_cfm rd_mem_addr_cfm; + + //Read crystal provided by CPU or not. + ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500148, &rd_mem_addr_cfm); + if (ret) { + AICWFDBG(LOGERROR, "%x rd fail: %d\n", 0x40500148, ret); + return -1; + } + + AICWFDBG(LOGDEBUG, "%s rd_mem_addr_cfm.memdata:%x \r\n", __func__, rd_mem_addr_cfm.memdata); + + if(!(rd_mem_addr_cfm.memdata & 0x01)){ + AICWFDBG(LOGINFO, "%s Crystal not provided by CPU \r\n", __func__); + return 0; + }else{ + AICWFDBG(LOGINFO, "%s Crystal provided by CPU \r\n", __func__); + //Read 0x40505010 value to check bbpll set or not. + ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40505010, &rd_mem_addr_cfm); + if(ret < 0){ + AICWFDBG(LOGERROR, "%s error ret_val:%d\r\n", __func__, ret); + return -1; + } + + if((rd_mem_addr_cfm.memdata >> 29) == 3){ + AICWFDBG(LOGERROR, "%s Not need to set \r\n", __func__); + return 0; + }else{ + rd_mem_addr_cfm.memdata |= ((0x1 << 29) | (0x1 << 30)); + rd_mem_addr_cfm.memdata &= (~(0x1 << 31)); + rwnx_send_dbg_mem_write_req(rwnx_hw, 0x40505010, rd_mem_addr_cfm.memdata); + } + } + return 0; +} +//Crystal provided by CPU (end) + + void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) { int syscfg_num; @@ -1698,6 +1958,9 @@ void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) int ret, cnt; const u32 mem_addr = 0x40500000; struct dbg_mem_read_cfm rd_mem_addr_cfm; +#ifdef CONFIG_OOB + int oobcfg_num; +#endif ret = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm); if (ret) { @@ -1719,6 +1982,14 @@ void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) //printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); AICWFDBG(LOGINFO, "chip_id=%x, chip_sub_id=%x!!\n", chip_id, chip_sub_id); + //Crystal provided by CPU (start) + ret = set_bbpll_config(rwnx_hw); + if (ret) { + AICWFDBG(LOGERROR, "set_bbpll_config fail: %d\n", ret); + return; + } + //Crystal provided by CPU (end) + ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x40500010, &rd_mem_addr_cfm); AICWFDBG(LOGDEBUG, "[0x40500010]=%x\n", rd_mem_addr_cfm.memdata); @@ -1747,7 +2018,7 @@ void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) return; } } - } else if (chip_sub_id == 1) { + } else if ((chip_sub_id == 1) || (chip_sub_id == 2)) { syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; for (cnt = 0; cnt < syscfg_num; cnt++) { ret = rwnx_send_dbg_mem_write_req(rwnx_hw, syscfg_tbl_8800dc_sdio_u02[cnt][0], syscfg_tbl_8800dc_sdio_u02[cnt][1]); @@ -1758,7 +2029,18 @@ void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) } } } - +#ifdef CONFIG_OOB + if ((chip_sub_id == 1) || (chip_sub_id == 2)) { + oobcfg_num = sizeof(oobcfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; + for (cnt = 0; cnt < oobcfg_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(rwnx_hw, oobcfg_tbl_8800dc_sdio_u02[cnt][0], oobcfg_tbl_8800dc_sdio_u02[cnt][1]); + if (ret) { + AICWFDBG(LOGERROR, "%x write fail: %d\n", oobcfg_tbl_8800dc_sdio_u02[cnt][0], ret); + return; + } + } + } +#endif if (IS_CHIP_ID_H()) { syscfg_num = sizeof(syscfg_tbl_masked_8800dc_h) / sizeof(u32) / 3; p_syscfg_msk_tbl = syscfg_tbl_masked_8800dc_h; @@ -1800,6 +2082,7 @@ void system_config_8800dc(struct aic_sdio_dev *rwnx_hw) } +extern int adap_test; void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) { @@ -1822,6 +2105,11 @@ void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) u32 jump_tbl_size = 0; u32 patch_tbl_func_num = 0; + //adap test + int adap_patch_num = 0; + //adap test + + array2_tbl_t jump_tbl_base = NULL; array2_tbl_t patch_tbl_func_base = NULL; array2_tbl_t patch_tbl_wifisetting_8800dc_base = NULL; @@ -1879,6 +2167,19 @@ void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) } } +//adap test + if(adap_test){ + AICWFDBG(LOGINFO, "%s for adaptivity test \r\n", __func__); + adap_patch_num = sizeof(adaptivity_patch_tbl_8800dc)/sizeof(u32)/2; + for(cnt = 0; cnt < adap_patch_num; cnt++) + { + if((ret = rwnx_send_dbg_mem_write_req(rwnx_hw, wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0], adaptivity_patch_tbl_8800dc[cnt][1]))) { + AICWFDBG(LOGERROR, "%x write fail\n", wifisetting_cfg_addr + adaptivity_patch_tbl_8800dc[cnt][0]); + } + } + } +//adap test + if (ldpc_cfg_size > 512) {// > 0.5KB data for (i = 0; i < (ldpc_cfg_size - 512); i += 512) {//each time write 0.5KB ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ldpc_cfg_addr + i, 512, ldpc_cfg_ram + i / 4); @@ -1915,11 +2216,21 @@ void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw) #if !defined(CONFIG_FPGA_VERIFICATION) if ((IS_CHIP_ID_H())) { + #if defined(CONFIG_EXT_FEM_8800DCDW) + txgain_cfg_size = sizeof(txgain_map_femkct_h); + txgain_cfg_array = (u32 *)txgain_map_femkct_h; + #else txgain_cfg_size = sizeof(txgain_map_h); txgain_cfg_array = (u32 *)txgain_map_h; + #endif } else { + #if defined(CONFIG_EXT_FEM_8800DCDW) + txgain_cfg_size = sizeof(txgain_map_femkct); + txgain_cfg_array = (u32 *)txgain_map_femkct; + #else txgain_cfg_size = sizeof(txgain_map); txgain_cfg_array = (u32 *)txgain_map; + #endif } ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, txgain_cfg_addr, txgain_cfg_size, txgain_cfg_array); if (ret) { @@ -2207,4 +2518,25 @@ int aicwf_dpd_result_write_8800dc(void *buf, int buf_len) #endif /* !CONFIG_FORCE_DPD_CALIB */ #endif - +#ifdef CONFIG_LOFT_CALIB +int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev) +{ + int ret = 0; + uint32_t fw_addr, boot_type; + ret = aicwf_plat_calib_load_8800dc(sdiodev); + if (ret) { + AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); + return ret; + } + /* fw start */ + fw_addr = 0x00130009; + boot_type = HOST_START_APP_FNCALL; + AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type); + ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL); + if (ret) { + AICWFDBG(LOGINFO, "start app fail: %d\n", ret); + return ret; + } + return ret; +} +#endif diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.h index 67074cecf..48bb9531c 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic8800dc_compat.h @@ -30,6 +30,9 @@ int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev, rf_misc_ram_lite_ int aicwf_dpd_result_write_8800dc(void *buf, int buf_len); #endif/* !CONFIG_FORCE_DPD_CALIB */ #endif +#ifdef CONFIG_LOFT_CALIB +int aicwf_loft_calib_8800dc(struct aic_sdio_dev *sdiodev); +#endif #endif diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.c index 5d7e6bbb3..9c665f246 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.c @@ -998,7 +998,7 @@ int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_o *valid_out = 0; } if (testmode == FW_RFTEST_MODE) { - + uint32_t vect1 = 0; uint32_t vect2 = 0; cfg_base = RAM_LMAC_FW_ADDR + 0x0004; @@ -1054,26 +1054,30 @@ int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_o } return ret; } +#endif +#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev) { int ret = 0; if (chip_sub_id == 1) { ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_U02); if (ret) { - AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); + AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); return ret; } } else if (chip_sub_id == 2) { ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_H_U02); if (ret) { - AICWFDBG(LOGINFO, "load rftest bin fail: %d\n", ret); + AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret); return ret; } } return ret; } +#endif +#ifdef CONFIG_DPD #ifndef CONFIG_FORCE_DPD_CALIB int is_file_exist(char* name) { @@ -1168,6 +1172,15 @@ static int rwnx_plat_patch_load(struct aic_sdio_dev *sdiodev) } #endif else + #elif defined(CONFIG_LOFT_CALIB) + if (1) { + AICWFDBG(LOGINFO, "loft calib\n"); + ret = aicwf_loft_calib_8800dc(sdiodev); + if (ret) { + AICWFDBG(LOGINFO, "loft calib fail: %d\n", ret); + return ret; + } + } else #endif { ret = aicwf_misc_ram_init_8800dc(sdiodev); @@ -1920,13 +1933,18 @@ int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev) if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) return -1; - aicbsp_info.chip_rev = (u8)(rd_mem_addr_cfm.memdata >> 16); + aicbsp_info.chip_rev = (u8)((rd_mem_addr_cfm.memdata >> 16) & 0x3F); + is_chip_id_h = (u8)(((rd_mem_addr_cfm.memdata >> 16) & 0xC0) == 0xC0); btenable = 1; - - if (aicbsp_info.chip_rev == CHIP_REV_U01) - aicbsp_firmware_list = fw_8800d80_u01; - if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) - aicbsp_firmware_list = fw_8800d80_u02; + if (is_chip_id_h) { + AICWFDBG(LOGINFO, "IS_CHIP_ID_H \n"); + aicbsp_firmware_list = fw_8800d80_h_u02; + } else { + if (aicbsp_info.chip_rev == CHIP_REV_U01) + aicbsp_firmware_list = fw_8800d80_u01; + if (aicbsp_info.chip_rev == CHIP_REV_U02 || aicbsp_info.chip_rev == CHIP_REV_U03) + aicbsp_firmware_list = fw_8800d80_u02; + } if (aicbsp_system_config_8800d80(sdiodev)) return -1; } diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.h index 4755875ea..566837c60 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_driver.h @@ -46,6 +46,7 @@ extern int aicwf_dbg_level_bsp; #define AICWF_LOG "AICWFDBG(" +#ifdef DEBUG #define AICWFDBG(level, args, arg...) \ do { \ if (aicwf_dbg_level_bsp & level) { \ @@ -60,6 +61,12 @@ do { \ } \ } while (0) +#else + +#define AICWFDBG(level, args, arg...) +#define RWNX_DBG(fmt, ...) + +#endif /// Message structure for MSGs from Emb to App struct ipc_e2a_msg { u16 id; ///< Message id. @@ -312,6 +319,8 @@ int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev); int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev); #ifdef CONFIG_DPD int aicwf_misc_ram_valid_check_8800dc(struct aic_sdio_dev *sdiodev, int *valid_out); +#endif +#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev); #endif @@ -371,10 +380,16 @@ int aicbsp_resv_mem_deinit(void); #define RWNX_MAC_CALIB_BASE_NAME_8800DC "fmacfw_calib_8800dc" #define RWNX_MAC_CALIB_NAME_8800DC_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin" +#ifdef CONFIG_SDIO_BT +#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_hbt_u02.bin" +#else #define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_h_u02.bin" +#endif -#ifdef CONFIG_DPD +#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB) #define ROM_FMAC_CALIB_ADDR 0x00130000 +#endif +#ifdef CONFIG_DPD #ifndef CONFIG_FORCE_DPD_CALIB #define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin" #endif @@ -389,13 +404,21 @@ int aicbsp_resv_mem_deinit(void); #define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc" #define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin" #define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin" +#ifdef CONFIG_SDIO_BT +#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_hbt_u02.bin" +#else #define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_h_u02.bin" #endif +#endif #define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc" #define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin" #define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin" +#ifdef CONFIG_SDIO_BT +#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_hbt_u02.bin" +#else #define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_h_u02.bin" +#endif #define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc" #define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin" @@ -492,8 +515,12 @@ enum chip_rev { #define AICBT_BTMODE_DEFAULT_8800d80 AICBT_BTMODE_BT_ONLY_COANT #define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW +#ifdef CONFIG_SDIO_BT +#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_MB +#else #define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART -#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_115200 +#endif +#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M #define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE #define AICBT_LPM_ENABLE_DEFAULT 0 #define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL @@ -501,9 +528,8 @@ enum chip_rev { #define AICBT_TXPWR_LVL_DEFAULT_8800d80 AICBT_TXPWR_LVL_8800d80 -#define AIC_IRQ_WAKE_FLAG 0 // 0: rising edge, 1: falling edge -#define FEATURE_SDIO_CLOCK 10000000 // 0: default, other: target clock rate -#define FEATURE_SDIO_CLOCK_V3 50000000 // 0: default, other: target clock rate +#define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate +#define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate #define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180° struct aicbt_patch_table { @@ -562,5 +588,6 @@ extern const struct aicbsp_firmware fw_8800dc_u02[]; extern const struct aicbsp_firmware fw_8800dc_h_u02[]; extern const struct aicbsp_firmware fw_8800d80_u01[]; extern const struct aicbsp_firmware fw_8800d80_u02[]; +extern const struct aicbsp_firmware fw_8800d80_h_u02[]; #endif diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_main.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_main.c index e9849cef3..1bbc2fe5d 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_main.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aic_bsp_main.c @@ -27,7 +27,11 @@ const struct aicbsp_firmware fw_u02[] = { .bt_adid = "fw_adid.bin", .bt_patch = "fw_patch.bin", .bt_table = "fw_patch_table.bin", + #ifdef CONFIG_SDIO_BT + .wl_fw = "fmacfwbt.bin" + #else .wl_fw = "fmacfw.bin" + #endif }, [AICBSP_CPMODE_TEST] = { .desc = "rf test mode(sdio u02)", @@ -46,6 +50,8 @@ const struct aicbsp_firmware fw_u03[] = { .bt_table = "fw_patch_table_u03.bin", #ifdef CONFIG_MCU_MESSAGE .wl_fw = "fmacfw_8800m_custmsg.bin" + #elif defined(CONFIG_SDIO_BT) + .wl_fw = "fmacfwbt.bin" #else .wl_fw = "fmacfw.bin" #endif @@ -140,7 +146,33 @@ const struct aicbsp_firmware fw_8800d80_u02[] = { .bt_adid = "fw_adid_8800d80_u02.bin", .bt_patch = "fw_patch_8800d80_u02.bin", .bt_table = "fw_patch_table_8800d80_u02.bin", + #ifdef CONFIG_SDIO_BT + .wl_fw = "fmacfwbt_8800d80_u02.bin" + #else .wl_fw = "fmacfw_8800d80_u02.bin" + #endif + }, + + [AICBSP_CPMODE_TEST] = { + .desc = "rf test mode(8800d80 sdio u02)", + .bt_adid = "fw_adid_8800d80_u02.bin", + .bt_patch = "fw_patch_8800d80_u02.bin", + .bt_table = "fw_patch_table_8800d80_u02.bin", + .wl_fw = "lmacfw_rf_8800d80_u02.bin" + }, +}; + +const struct aicbsp_firmware fw_8800d80_h_u02[] = { + [AICBSP_CPMODE_WORK] = { + .desc = "normal work mode(8800d80 sdio h_u02)", + .bt_adid = "fw_adid_8800d80_u02.bin", + .bt_patch = "fw_patch_8800d80_u02.bin", + .bt_table = "fw_patch_table_8800d80_u02.bin", + #ifdef CONFIG_SDIO_BT + .wl_fw = "fmacfwbt_8800d80_h_u02.bin" + #else + .wl_fw = "fmacfw_8800d80_h_u02.bin" + #endif }, [AICBSP_CPMODE_TEST] = { @@ -157,7 +189,11 @@ struct aicbsp_info_t aicbsp_info = { .hwinfo = AICBSP_HWINFO_DEFAULT, .cpmode = AICBSP_CPMODE_DEFAULT, .fwlog_en = AICBSP_FWLOG_EN_DEFAULT, - .irqf = AIC_IRQ_WAKE_FLAG, +#ifdef CONFIG_IRQ_FALL + .irqf = 1, +#else + .irqf = 0, +#endif }; struct mutex aicbsp_power_lock; @@ -343,7 +379,7 @@ static int __init aicbsp_init(void) } mutex_init(&aicbsp_power_lock); -#ifdef CONFIG_PLATFORM_ROCKCHIP +#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); #endif return 0; @@ -354,7 +390,7 @@ extern struct aic_sdio_dev *aicbsp_sdiodev; static void __exit aicbsp_exit(void) { -#ifdef CONFIG_PLATFORM_ROCKCHIP +#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 if(aicbsp_sdiodev){ aicbsp_sdio_exit(); } diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.c index fa9df3c82..75d235bf4 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.c @@ -48,6 +48,8 @@ static void aicbsp_platform_power_off(void); struct aic_sdio_dev *aicbsp_sdiodev = NULL; static struct semaphore *aicbsp_notify_semaphore; +static struct semaphore *aicbsp_probe_semaphore = NULL; + static const struct sdio_device_id aicbsp_sdmmc_ids[]; static bool aicbsp_load_fw_in_fdrv = false; @@ -84,10 +86,7 @@ extern int testmode; static int aicbsp_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id) { if (func && (func->num != 2)) - { - printk("func_num = %d \r\n",func->num); return 0; - } if(func->vendor != SDIO_VENDOR_ID_AIC8801 && func->device != SDIO_DEVICE_ID_AIC8801 && @@ -100,10 +99,6 @@ static int aicbsp_dummy_probe(struct sdio_func *func, const struct sdio_device_i printk("VID:%x DID:%X \r\n", func->vendor, func->device); aicbsp_load_fw_in_fdrv = true; } - else - { - printk("VID:%x DID:%X \r\n", func->vendor, func->device); - } if (aicbsp_notify_semaphore) up(aicbsp_notify_semaphore); @@ -190,15 +185,7 @@ int aicbsp_set_subsys(int subsys, int state) aicbsp_sdio_release(aicbsp_sdiodev); #endif -#ifdef CONFIG_PLATFORM_ROCKCHIP -#ifdef CONFIG_GPIO_WAKEUP - //BT_SLEEP:true,BT_WAKEUP:false - rfkill_rk_sleep_bt(true); - printk("%s BT wake default to SLEEP\r\n", __func__); -#endif -#endif - -#ifdef CONFIG_PLATFORM_ROCKCHIP2 +#if defined CONFIG_PLATFORM_ROCKCHIP || defined CONFIG_PLATFORM_ROCKCHIP2 #ifdef CONFIG_GPIO_WAKEUP //BT_SLEEP:true,BT_WAKEUP:false rfkill_rk_sleep_bt(true); @@ -279,6 +266,16 @@ static int aicbsp_sdio_probe(struct sdio_func *func, struct aicwf_bus *bus_if; int err = -ENODEV; + if (func == NULL) { + sdio_err("%s func is null\n", __func__); + return err; + } + + if (aicbsp_probe_semaphore == NULL) { + sdio_err("%s bsp_probe_semaphore is null\n", __func__); + return err; + } + sdio_dbg("%s:%d vid:0x%04X did:0x%04X\n", __func__, func->num, func->vendor, func->device); @@ -298,8 +295,11 @@ static int aicbsp_sdio_probe(struct sdio_func *func, return err; } - func = func->card->sdio_func[1 - 1]; //replace 2 with 1 host = func->card->host; + host->caps |= MMC_CAP_NONREMOVABLE; + + func = func->card->sdio_func[1 - 1]; //replace 2 with 1 + sdio_dbg("%s after replace:%d\n", __func__, func->num); bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_KERNEL); @@ -346,9 +346,11 @@ static int aicbsp_sdio_probe(struct sdio_func *func, sdio_err("sdio bus init err\r\n"); goto fail; } - host->caps |= MMC_CAP_NONREMOVABLE; + aicbsp_platform_init(sdiodev); + up(aicbsp_probe_semaphore); + return 0; fail: aicwf_sdio_func_deinit(sdiodev); @@ -358,33 +360,37 @@ fail: return err; } + static void aicbsp_sdio_remove(struct sdio_func *func) { struct mmc_host *host; struct aicwf_bus *bus_if = NULL; struct aic_sdio_dev *sdiodev = NULL; - sdio_dbg("%s\n", __func__); + AICWFDBG(LOGINFO, "%s\n", __func__); if (aicbsp_sdiodev == NULL) { - sdio_dbg("%s: allready unregister\n", __func__); - return; + AICWFDBG(LOGERROR, "%s: allready unregister\n", __func__); + goto done; + } + if ((func == NULL) || (&func->dev == NULL)) { + AICWFDBG(LOGERROR, "%s, sdio func is null\n", __func__); + goto done; } - bus_if = aicbsp_get_drvdata(&func->dev); - - if (!bus_if) { - AICWFDBG(LOGERROR, "%s bus_if is NULL \r\n", __func__); - return; - } - - func = aicbsp_sdiodev->func; host = func->card->host; host->caps &= ~MMC_CAP_NONREMOVABLE; + bus_if = aicbsp_get_drvdata(&func->dev); + + if (!bus_if) { + AICWFDBG(LOGERROR, "%s bus_if is NULL \r\n", __func__); + goto done; + } + sdiodev = bus_if->bus_priv.sdio; if (!sdiodev) { - AICWFDBG(LOGERROR, "%s sdiodev is NULL \r\n", __func__); - return; + AICWFDBG(LOGERROR, "%s sdiodev is NULL \r\n", __func__); + goto done; } aicwf_sdio_release(sdiodev); @@ -392,29 +398,27 @@ static void aicbsp_sdio_remove(struct sdio_func *func) dev_set_drvdata(&sdiodev->func->dev, NULL); kfree(sdiodev); - kfree(bus_if); + +done: + if (bus_if) + kfree(bus_if); aicbsp_sdiodev = NULL; + aicbsp_probe_semaphore = NULL; sdio_dbg("%s done\n", __func__); } +#ifdef SDIO_REMOVEABLE static int aicbsp_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); int err; mmc_pm_flag_t sdio_flags; -#ifdef CONFIG_PLATFORM_ROCKCHIP +#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) #ifdef CONFIG_GPIO_WAKEUP //BT_SLEEP:true,BT_WAKEUP:false rfkill_rk_sleep_bt(false); #endif -#endif - -#ifdef CONFIG_PLATFORM_ROCKCHIP2 -#ifdef CONFIG_GPIO_WAKEUP - //BT_SLEEP:true,BT_WAKEUP:false - rfkill_rk_sleep_bt(false); -#endif #endif sdio_dbg("%s, func->num = %d\n", __func__, func->num); @@ -434,7 +438,7 @@ static int aicbsp_sdio_suspend(struct device *dev) return err; } -#ifdef CONFIG_PLATFORM_ROCKCHIP +#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) #ifdef CONFIG_GPIO_WAKEUP //BT_SLEEP:true,BT_WAKEUP:false rfkill_rk_sleep_bt(true); @@ -442,15 +446,6 @@ static int aicbsp_sdio_suspend(struct device *dev) #endif #endif -#ifdef CONFIG_PLATFORM_ROCKCHIP2 -#ifdef CONFIG_GPIO_WAKEUP - //BT_SLEEP:true,BT_WAKEUP:false - rfkill_rk_sleep_bt(true); - printk("%s BT wake to SLEEP\r\n", __func__); -#endif -#endif - - return 0; } @@ -458,8 +453,16 @@ static int aicbsp_sdio_resume(struct device *dev) { sdio_dbg("%s\n", __func__); +#if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) +#ifdef CONFIG_GPIO_WAKEUP + //BT_SLEEP:true,BT_WAKEUP:false + rfkill_rk_sleep_bt(false); +#endif +#endif + return 0; } +#endif static const struct sdio_device_id aicbsp_sdmmc_ids[] = { {SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)}, @@ -512,7 +515,6 @@ static int aicbsp_platform_power_on(void) rockchip_wifi_set_carddetect(1); #endif /*CONFIG_PLATFORM_ROCKCHIP2*/ - sema_init(&aic_chipup_sem, 0); ret = aicbsp_reg_sdio_notify(&aic_chipup_sem); if (ret) { @@ -528,9 +530,7 @@ static int aicbsp_platform_power_on(void) sunxi_mmc_rescan_card(aicbsp_bus_index); #endif //CONFIG_PLATFORM_ALLWINNER - sdio_dbg("%s Get semaphore ... \n", __func__); - if (down_timeout(&aic_chipup_sem, msecs_to_jiffies(4000)) == 0) { - sdio_dbg("%s Get semaphore success \n", __func__); + if (down_timeout(&aic_chipup_sem, msecs_to_jiffies(2000)) == 0) { aicbsp_unreg_sdio_notify(); if(aicbsp_load_fw_in_fdrv){ printk("%s load fw in fdrv\r\n", __func__); @@ -588,11 +588,22 @@ static void aicbsp_platform_power_off(void) int aicbsp_sdio_init(void) { + struct semaphore aic_chipup_sem; + + sema_init(&aic_chipup_sem, 0); + aicbsp_probe_semaphore = &aic_chipup_sem; + if (sdio_register_driver(&aicbsp_sdio_driver)) { return -1; } else { //may add mmc_rescan here } + if (down_timeout(aicbsp_probe_semaphore, msecs_to_jiffies(2000)) != 0){ + printk("%s aicbsp_sdio_probe fail\r\n", __func__); + return -1; + } + + return 0; } @@ -1618,22 +1629,33 @@ void aicwf_sdio_release_func2(struct aic_sdio_dev *sdiodev) void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) { - struct aicwf_bus *bus_if; + struct aicwf_bus *bus_if = NULL; + struct aicwf_bus *bus_if_t = NULL; int ret = 0; sdio_dbg("%s\n", __func__); + if (sdiodev->func == NULL) { + printk("%s, NULL sdio func\n", __func__); + return; + } bus_if = aicbsp_get_drvdata(sdiodev->dev); - bus_if->state = BUS_DOWN_ST; + if (bus_if) + bus_if->state = BUS_DOWN_ST; - sdio_claim_host(sdiodev->func); - //disable sdio interrupt - ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); - if (ret < 0) { - sdio_err("reg:%d write failed!, ret=%d\n", sdiodev->sdio_reg.intr_config_reg, ret); + bus_if_t = dev_get_drvdata(sdiodev->dev); + + if ((bus_if_t != NULL) && (sdiodev->bus_if == bus_if_t)) { + sdio_dbg("%s bsp release\n", __func__); + sdio_claim_host(sdiodev->func); + //disable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); + if (ret < 0) { + sdio_err("reg:%d write failed!, ret=%d\n", sdiodev->sdio_reg.intr_config_reg, ret); + } + sdio_release_irq(sdiodev->func); + sdio_release_host(sdiodev->func); } - sdio_release_irq(sdiodev->func); - sdio_release_host(sdiodev->func); if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ aicwf_sdio_release_func2(sdiodev); @@ -1651,6 +1673,8 @@ void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) rwnx_cmd_mgr_deinit(&sdiodev->cmd_mgr); } + + void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev) { sdio_dbg("%s\n", __func__); @@ -1720,7 +1744,6 @@ int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) #if 1//SDIO CLOCK SETTING if (feature.sdio_clock > 0) { host->ios.clock = feature.sdio_clock; - // for test host->ops->set_ios(host, &host->ios); sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); } @@ -1860,16 +1883,35 @@ int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev) void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) { - sdio_claim_host(sdiodev->func); - sdio_disable_func(sdiodev->func); - sdio_release_host(sdiodev->func); + struct aicwf_bus *bus_if = NULL; + + if (sdiodev->func == NULL) { + sdio_err("%s, NULL sdio func\n", __func__); + return; + } + + bus_if = dev_get_drvdata(sdiodev->dev); + if (bus_if == NULL) { + sdio_err("%s, bus_if is null\n", __func__); + return; + } + + if (sdiodev->bus_if == bus_if) { + sdio_dbg("%s bsp disable\n", __func__); + sdio_claim_host(sdiodev->func); + sdio_disable_func(sdiodev->func); + sdio_release_host(sdiodev->func); + } + if(sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW){ sdio_claim_host(sdiodev->func_msg); sdio_disable_func(sdiodev->func_msg); sdio_release_host(sdiodev->func_msg); } + } + void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) { int ret; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.h index 582ba94df..68efaf5f6 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio.h @@ -108,6 +108,7 @@ struct aic_sdio_dev { struct semaphore pwrctl_wakeup_sema; #endif u16 chipid; + u32 fw_version_uint; struct aic_sdio_reg sdio_reg; void (*sdio_hal_irqhandler) (struct sdio_func *func); }; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio_txrxif.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio_txrxif.c index 37297f1b8..82bacf945 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio_txrxif.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/aicsdio_txrxif.c @@ -47,12 +47,14 @@ int aicwf_bus_init(uint bus_hdrlen, struct device *dev) if (IS_ERR(bus_if->bustx_thread)) { bus_if->bustx_thread = NULL; txrx_err("aicwf_bustx_thread run fail\n"); + ret = -1; goto fail; } if (IS_ERR(bus_if->busrx_thread)) { bus_if->busrx_thread = NULL; txrx_err("aicwf_bustx_thread run fail\n"); + ret = -1; goto fail; } diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/rwnx_version_gen.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/rwnx_version_gen.h index 5185e9229..6ce7186ae 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/rwnx_version_gen.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_bsp/rwnx_version_gen.h @@ -1,4 +1,4 @@ #define RWNX_VERS_REV "241c091M (master)" #define RWNX_VERS_MOD "6.4.3.0" #define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" -#define RELEASE_DATE "2023_1219_3cf85031" +#define RELEASE_DATE "2024_0615_c3cb37b3" diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_btlpm/Makefile b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_btlpm/Makefile index cd63d62b9..6d59301f9 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_btlpm/Makefile +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_btlpm/Makefile @@ -12,38 +12,23 @@ CONFIG_PLATFORM_AMLOGIC ?= n CONFIG_PLATFORM_UBUNTU ?= y -CONFIG_SUPPORT_LPM = y +CONFIG_SUPPORT_LPM ?= n CONFIG_AUTO_PM ?= n aic8800_btlpm-y := \ aic_bluetooth_main.o \ rfkill.o \ -ifeq ($(CONFIG_PLATFORM_UBUNTU), n) - aic8800_btlpm-$(CONFIG_SUPPORT_LPM) += lpm.o -endif +aic8800_btlpm-$(CONFIG_SUPPORT_LPM) += lpm.o ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) ccflags-$(CONFIG_AUTO_PM) += -DCONFIG_AUTO_PM ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) -KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel -ARCH ?= arm -CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3229/Android10/SDK/kernel/ -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android10/SDK/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/ -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux#-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- -#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/kernel -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- - +ARCH = arm64 +KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel +CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ccflags-y += -DANDROID_PLATFORM endif diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/Makefile b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/Makefile index 778cef87f..390d72fa4 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/Makefile +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/Makefile @@ -1,8 +1,8 @@ EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) EXTRA_CFLAGS += -Wno-implicit-fallthrough -EXTRA_CFLAGS += -Wno-unused-function +#EXTRA_CFLAGS += -Wno-unused-function #EXTRA_CFLAGS += -Wno-maybe-uninitialized -# EXTRA_CFLAGS += -Wno-unused-variable +#EXTRA_CFLAGS += -Wno-unused-variable RWNX_VERS_NUM := 6.4.3.0 @@ -73,6 +73,7 @@ CONFIG_RADAR_OR_IR_DETECT =n CONFIG_DOWNLOAD_FW =n CONFIG_RFTEST=y CONFIG_USB_BT =y +CONFIG_SDIO_BT=n CONFIG_USE_5G ?= y CONFIG_SDIO_PWRCTRL ?= y CONFIG_CREATE_TRACE_POINTS = n @@ -80,7 +81,7 @@ CONFIG_TXRX_THREAD_PRIO = y # CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw CONFIG_COEX = y CONFIG_RX_NETIF_RECV_SKB = y -CONFIG_GPIO_WAKEUP = n +CONFIG_GPIO_WAKEUP ?= n CONFIG_SET_VENDOR_EXTENSION_IE = n CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y CONFIG_WPA3_FOR_OLD_KERNEL ?= n @@ -91,19 +92,35 @@ CONFIG_WIFI_SUSPEND_FOR_LINUX = n # Need to set fw path in BOARD_KERNEL_CMDLINE CONFIG_USE_FW_REQUEST = n CONFIG_USE_P2P0=n +CONFIG_TX_NETIF_FLOWCTRL = n +CONFIG_ONE_TXQ = n CONFIG_BR_SUPPORT =n BR_NAME = br0 CONFIG_FDRV_NO_REG_SDIO=n CONFIG_SCHED_SCAN = n -CONFIG_OOB = n +CONFIG_OOB ?= n CONFIG_USE_CUSTOMER_MAC = n -CONFIG_PREALLOC_TXQ = y +CONFIG_PREALLOC_TXQ ?= y CONFIG_DPD = y CONFIG_FORCE_DPD_CALIB = y -CONFIG_FILTER_TCP_ACK =n -CONFIG_RESV_MEM_SUPPORT = y +CONFIG_LOFT_CALIB = n +CONFIG_FILTER_TCP_ACK =y +CONFIG_RESV_MEM_SUPPORT ?= y CONFIG_GKI = n CONFIG_TEMP_COMP = n +CONFIG_EXT_FEM_8800DCDW = n +# CONFIG_MCC = n for sta and p2p concurrent in same channel. +CONFIG_MCC = y + +ifneq ($(CONFIG_WIRELESS_EXT), y) +CONFIG_USE_WIRELESS_EXT = n +endif + +ifeq ($(CONFIG_EXT_FEM_8800DCDW), y) +CONFIG_DPD = n +CONFIG_FORCE_DPD_CALIB = n +CONFIG_LOFT_CALIB = y +endif # Support of MU-MIMO transmission (need FW support) ifeq ($(CONFIG_RWNX_BFMER), y) @@ -153,6 +170,7 @@ $(MODULE_NAME)-y := \ aicwf_compat_8800d80.o \ rwnx_wakelock.o \ regdb.o \ + aic_priv_cmd.o \ aicwf_rx_prealloc.o $(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o @@ -166,6 +184,7 @@ $(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o $(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o $(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o $(MODULE_NAME)-$(CONFIG_FILTER_TCP_ACK) += aicwf_tcp_ack.o +$(MODULE_NAME)-$(CONFIG_SDIO_BT) += aic_btsdio.o $(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o $(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o @@ -245,10 +264,14 @@ ccflags-$(CONFIG_USE_CUSTOMER_MAC) += -DCONFIG_USE_CUSTOMER_MAC ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ ccflags-$(CONFIG_DPD) += -DCONFIG_DPD ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD +ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB ccflags-$(CONFIG_FILTER_TCP_ACK) += -DCONFIG_FILTER_TCP_ACK +ccflags-$(CONFIG_SDIO_BT) += -DCONFIG_SDIO_BT ccflags-$(CONFIG_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT ccflags-$(CONFIG_GKI) += -DCONFIG_GKI ccflags-$(CONFIG_TEMP_COMP) += -DCONFIG_TEMP_COMP +ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW +ccflags-$(CONFIG_MCC) += -DCONFIG_MCC ifeq ($(CONFIG_SDIO_SUPPORT), y) @@ -287,8 +310,13 @@ ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD ccflags-$(CONFIG_RADAR_DETECT) += -DRADAR_OR_IR_DETECT ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB +ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ +ccflags-$(CONFIG_TX_NETIF_FLOWCTRL) += -DCONFIG_TX_NETIF_FLOWCTRL -# Platform support list +ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) +MAKEFLAGS +=-j$(shell nproc) + +########## Platform support list ########## CONFIG_PLATFORM_ROCKCHIP ?= n CONFIG_PLATFORM_ROCKCHIP2 ?= n CONFIG_PLATFORM_ALLWINNER ?= n @@ -296,32 +324,10 @@ CONFIG_PLATFORM_INGENIC_T20 ?= n CONFIG_PLATFORM_AMLOGIC ?= n CONFIG_PLATFORM_UBUNTU ?= y -ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) - ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) -#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- -#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/ -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel -#ARCH ?= arm -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -#KDIR ?= /home/yaya/E/Rockchip/3566/Android/kernel -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/ -#ARCH ?= arm64 -#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel -KDIR ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/kernel -#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel -ARCH ?= arm64 -CROSS_COMPILE ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +ARCH := arm64 +KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel +CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP ccflags-y += -DANDROID_PLATFORM endif @@ -363,6 +369,7 @@ MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ ARCH ?= x86_64 CROSS_COMPILE ?= endif +########################################### all: modules diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_btsdio.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_btsdio.c new file mode 100755 index 000000000..643f94698 --- /dev/null +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_btsdio.c @@ -0,0 +1,1310 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "aic_btsdio.h" +#include "rwnx_msg_tx.h" + +static spinlock_t queue_lock; + +static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) +{ + struct sk_buff *skb; + + if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) { + skb_reserve(skb, BT_SKB_RESERVE); + bt_cb(skb)->incoming = 0; + } + return skb; +} + +static spinlock_t queue_lock; +static spinlock_t dlfw_lock; +static volatile uint16_t dlfw_dis_state = 0; + +/* Global parameters for bt usb char driver */ +#define BT_CHAR_DEVICE_NAME "aicbt_dev" +struct mutex btchr_mutex; +static struct sk_buff_head btchr_readq; +static wait_queue_head_t btchr_read_wait; +static wait_queue_head_t bt_dlfw_wait; +static int bt_char_dev_registered; +static dev_t bt_devid; /* bt char device number */ +static struct cdev bt_char_dev; /* bt character device structure */ +static struct class *bt_char_class; /* device class for usb char driver */ +static int bt_reset = 0; +//int aic_queue_cnt(void); +/* HCI device & lock */ +DEFINE_RWLOCK(hci_dev_lock); + +struct hci_dev *ghdev = NULL; + +static struct sk_buff *aic_skb_queue[QUEUE_SIZE]; +static int aic_skb_queue_front = 0; +static int aic_skb_queue_rear = 0; + +static inline int check_set_dlfw_state_value(uint16_t change_value) +{ + spin_lock(&dlfw_lock); + if(!dlfw_dis_state) { + dlfw_dis_state = change_value; + } + spin_unlock(&dlfw_lock); + return dlfw_dis_state; +} + +static inline void set_dlfw_state_value(uint16_t change_value) +{ + spin_lock(&dlfw_lock); + dlfw_dis_state = change_value; + spin_unlock(&dlfw_lock); +} + +static void print_acl(struct sk_buff *skb, int direction) +{ +#if PRINT_ACL_DATA + //uint wlength = skb->len; + u16 *handle = (u16 *)(skb->data); + u16 len = *(handle+1); + //u8 *acl_data = (u8 *)(skb->data); + + AICBT_INFO("aic %s: direction %d, handle %04x, len %d", + __func__, direction, *handle, len); +#endif +} + +static void print_sco(struct sk_buff *skb, int direction) +{ +#if PRINT_SCO_DATA + uint wlength = skb->len; + u16 *handle = (u16 *)(skb->data); + u8 len = *(u8 *)(handle+1); + //u8 *sco_data =(u8 *)(skb->data); + + AICBT_INFO("aic %s: direction %d, handle %04x, len %d,wlength %d", + __func__, direction, *handle, len,wlength); +#endif +} + +int bt_bypass_event(struct sk_buff *skb) +{ + int ret = 0; + u8 *opcode = (u8*)(skb->data); + //u8 len = *(opcode+1); + //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); + + switch(opcode[1]) { + case HCI_EV_LE_Meta: + { + u8 subevent_code; + subevent_code = opcode[3]; + switch(subevent_code){ + case HCI_BLE_ADV_PKT_RPT_EVT: + case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: + { + if(aic_queue_cnt() > (QUEUE_SIZE-490)){ + printk("more adv report bypass\r\n"); + ret = 1; + } + } + break; + } + } + break; + default: + break; + } + return ret; +} + +int bt_sdio_recv(u8 *data,u32 data_len) +{ + struct sk_buff *skb; + int type= data[0]; + struct hci_dev *hdev; + u32 len = data_len; + //int ret=0; + hdev = hci_dev_get(0); + if (!hdev) { + AICWFDBG(LOGERROR,"%s: Failed to get hci dev[NULL]", __func__); + return -ENODEV; + } + + //printk("%s type %x len %d \n",__func__,type,len); + //bt_data_dump("bt_recv", ind->bt_data, 64); + + /*#if (CONFIG_BLUEDROID) || (HCI_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) + if (hci_recv_fragment(hdev, type, + ind->bt_data[0], + ind->data_len) < 0) { + AICWFDBG(LOGERROR,"%s: Corrupted event packet", __func__); + hdev->stat.err_rx++; + } + #endif*/ + skb = alloc_skb(len,GFP_ATOMIC); + if(!skb){ + AICWFDBG(LOGERROR, "alloc skb fail %s \n",__func__); + } + memcpy(skb_put(skb,len) ,data, len); + if(bt_bypass_event(skb)){ + kfree_skb(skb); + return 0; + } + //bt_data_dump("bt_skb", skb, skb->len); + + if(aic_enqueue(skb)<0){ + kfree_skb(skb); + }else{ + //printk("wake up \n"); + wake_up_interruptible(&btchr_read_wait); + } + return 0; +} + + +static int bypass_event(struct sk_buff *skb) +{ + int ret = 0; + u8 *opcode = (u8*)(skb->data); + //u8 len = *(opcode+1); + //printk("bypass_event %x,%x,%x,%x,%x\r\n",opcode[0],opcode[1],opcode[2],opcode[3],opcode[4]); + + switch(*opcode) { +#ifdef CONFIG_SUPPORT_VENDOR_APCF + case HCI_EV_CMD_COMPLETE: + { + u16 sub_opcpde; + sub_opcpde = ((u16)opcode[3]|(u16)(opcode[4])<<8); + if(sub_opcpde == 0xfd57){ + if(vendor_apcf_sent_done){ + vendor_apcf_sent_done--; + printk("apcf bypass\r\n"); + ret = 1; + } + } + } + break; +#endif//CONFIG_SUPPORT_VENDOR_APCF + case HCI_EV_LE_Meta: + { + u8 subevent_code; + subevent_code = opcode[2]; + switch(subevent_code){ + case HCI_BLE_ADV_PKT_RPT_EVT: + case HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT: + { + if(aic_queue_cnt() > (QUEUE_SIZE-100)){ + printk("more adv report bypass\r\n"); + ret = 1; + } + } + break; + } + } + break; + default: + break; + } + return ret; +} +static void print_event(struct sk_buff *skb) +{ +#if PRINT_CMD_EVENT + //uint wlength = skb->len; + //uint icount = 0; + u8 *opcode = (u8*)(skb->data); + //u8 len = *(opcode+1); + + printk("aic %s ", __func__); + switch (*opcode) { + case HCI_EV_INQUIRY_COMPLETE: + printk("HCI_EV_INQUIRY_COMPLETE"); + break; + case HCI_EV_INQUIRY_RESULT: + printk("HCI_EV_INQUIRY_RESULT"); + break; + case HCI_EV_CONN_COMPLETE: + printk("HCI_EV_CONN_COMPLETE"); + break; + case HCI_EV_CONN_REQUEST: + printk("HCI_EV_CONN_REQUEST"); + break; + case HCI_EV_DISCONN_COMPLETE: + printk("HCI_EV_DISCONN_COMPLETE"); + break; + case HCI_EV_AUTH_COMPLETE: + printk("HCI_EV_AUTH_COMPLETE"); + break; + case HCI_EV_REMOTE_NAME: + printk("HCI_EV_REMOTE_NAME"); + break; + case HCI_EV_ENCRYPT_CHANGE: + printk("HCI_EV_ENCRYPT_CHANGE"); + break; + case HCI_EV_CHANGE_LINK_KEY_COMPLETE: + printk("HCI_EV_CHANGE_LINK_KEY_COMPLETE"); + break; + case HCI_EV_REMOTE_FEATURES: + printk("HCI_EV_REMOTE_FEATURES"); + break; + case HCI_EV_REMOTE_VERSION: + printk("HCI_EV_REMOTE_VERSION"); + break; + case HCI_EV_QOS_SETUP_COMPLETE: + printk("HCI_EV_QOS_SETUP_COMPLETE"); + break; + case HCI_EV_CMD_COMPLETE: + printk("HCI_EV_CMD_COMPLETE"); + break; + case HCI_EV_CMD_STATUS: + printk("HCI_EV_CMD_STATUS"); + break; + case HCI_EV_ROLE_CHANGE: + printk("HCI_EV_ROLE_CHANGE"); + break; + case HCI_EV_NUM_COMP_PKTS: + printk("HCI_EV_NUM_COMP_PKTS"); + break; + case HCI_EV_MODE_CHANGE: + printk("HCI_EV_MODE_CHANGE"); + break; + case HCI_EV_PIN_CODE_REQ: + printk("HCI_EV_PIN_CODE_REQ"); + break; + case HCI_EV_LINK_KEY_REQ: + printk("HCI_EV_LINK_KEY_REQ"); + break; + case HCI_EV_LINK_KEY_NOTIFY: + printk("HCI_EV_LINK_KEY_NOTIFY"); + break; + case HCI_EV_CLOCK_OFFSET: + printk("HCI_EV_CLOCK_OFFSET"); + break; + case HCI_EV_PKT_TYPE_CHANGE: + printk("HCI_EV_PKT_TYPE_CHANGE"); + break; + case HCI_EV_PSCAN_REP_MODE: + printk("HCI_EV_PSCAN_REP_MODE"); + break; + case HCI_EV_INQUIRY_RESULT_WITH_RSSI: + printk("HCI_EV_INQUIRY_RESULT_WITH_RSSI"); + break; + case HCI_EV_REMOTE_EXT_FEATURES: + printk("HCI_EV_REMOTE_EXT_FEATURES"); + break; + case HCI_EV_SYNC_CONN_COMPLETE: + printk("HCI_EV_SYNC_CONN_COMPLETE"); + break; + case HCI_EV_SYNC_CONN_CHANGED: + printk("HCI_EV_SYNC_CONN_CHANGED"); + break; + case HCI_EV_SNIFF_SUBRATE: + printk("HCI_EV_SNIFF_SUBRATE"); + break; + case HCI_EV_EXTENDED_INQUIRY_RESULT: + printk("HCI_EV_EXTENDED_INQUIRY_RESULT"); + break; + case HCI_EV_IO_CAPA_REQUEST: + printk("HCI_EV_IO_CAPA_REQUEST"); + break; + case HCI_EV_SIMPLE_PAIR_COMPLETE: + printk("HCI_EV_SIMPLE_PAIR_COMPLETE"); + break; + case HCI_EV_REMOTE_HOST_FEATURES: + printk("HCI_EV_REMOTE_HOST_FEATURES"); + break; + default: + printk("unknow event"); + break; + } + printk("\n"); +#if 0 + printk("%02x,len:%d,", *opcode,len); + for (icount = 2; (icount < wlength) && (icount < 24); icount++) + printk("%02x ", *(opcode+icount)); + printk("\n"); +#endif +#endif +} + + +static inline ssize_t sdio_put_user(struct sk_buff *skb, + char __user *buf, int count) +{ + char __user *ptr = buf; + int len = min_t(unsigned int, skb->len, count); + + if (copy_to_user(ptr, skb->data, len)) + return -EFAULT; + + return len; +} + +int aic_enqueue(struct sk_buff *skb) +{ + unsigned long flags = 0; + int ret = 0; + spin_lock_irqsave(&queue_lock, flags); + if (aic_skb_queue_front == (aic_skb_queue_rear + 1) % QUEUE_SIZE) { + /* + * If queue is full, current solution is to drop + * the following entries. + */ + AICBT_WARN("%s: Queue is full, entry will be dropped", __func__); + ret = -1; + } else { + aic_skb_queue[aic_skb_queue_rear] = skb; + + aic_skb_queue_rear++; + aic_skb_queue_rear %= QUEUE_SIZE; + + } + spin_unlock_irqrestore(&queue_lock, flags); + return ret; +} + +static struct sk_buff *aic_dequeue_try(unsigned int deq_len) +{ + struct sk_buff *skb; + struct sk_buff *skb_copy; + unsigned long flags = 0; + + spin_lock_irqsave(&queue_lock, flags); + if (aic_skb_queue_front == aic_skb_queue_rear) { + AICBT_WARN("%s: Queue is empty", __func__); + spin_unlock_irqrestore(&queue_lock, flags); + return NULL; + } + + skb = aic_skb_queue[aic_skb_queue_front]; + if (deq_len >= skb->len) { + + aic_skb_queue_front++; + aic_skb_queue_front %= QUEUE_SIZE; + + /* + * Return skb addr to be dequeued, and the caller + * should free the skb eventually. + */ + spin_unlock_irqrestore(&queue_lock, flags); + return skb; + } else { + skb_copy = pskb_copy(skb, GFP_ATOMIC); + skb_pull(skb, deq_len); + /* Return its copy to be freed */ + spin_unlock_irqrestore(&queue_lock, flags); + return skb_copy; + } +} + +static inline int is_queue_empty(void) +{ + return (aic_skb_queue_front == aic_skb_queue_rear) ? 1 : 0; +} + +void aic_clear_queue(void) +{ + struct sk_buff *skb; + unsigned long flags = 0; + + spin_lock_irqsave(&queue_lock, flags); + while(!is_queue_empty()) { + skb = aic_skb_queue[aic_skb_queue_front]; + aic_skb_queue[aic_skb_queue_front] = NULL; + aic_skb_queue_front++; + aic_skb_queue_front %= QUEUE_SIZE; + if (skb) { + kfree_skb(skb); + } + } + spin_unlock_irqrestore(&queue_lock, flags); +} + +int aic_queue_cnt(void) +{ + int ret_cnt = 0; + unsigned long flags = 0; + + spin_lock_irqsave(&queue_lock, flags); + if(is_queue_empty()) { + ret_cnt = 0; + }else{ + if(aic_skb_queue_rear > aic_skb_queue_front){ + ret_cnt = aic_skb_queue_rear-aic_skb_queue_front; + }else{ + ret_cnt = aic_skb_queue_rear+QUEUE_SIZE-aic_skb_queue_front; + } + } + spin_unlock_irqrestore(&queue_lock, flags); + return ret_cnt; +} + +/* + * AicSemi - Integrate from hci_core.c + */ + +/* Get HCI device by index. + * Device is held on return. */ +struct hci_dev *hci_dev_get(int index) +{ + if (index != 0) + return NULL; + + return ghdev; +} + +/* ---- HCI ioctl helpers ---- */ +static int hci_dev_open(__u16 dev) +{ + struct hci_dev *hdev; + int ret = 0; + + AICBT_DBG("%s: dev %d", __func__, dev); + + hdev = hci_dev_get(dev); + if (!hdev) { + AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); + return -ENODEV; + } + + /*if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { + ret = -ENODEV; + goto done; + } + + if (test_bit(HCI_UP, &hdev->flags)) { + ret = -EALREADY; + goto done; + }*/ + +done: + return ret; +} + +static int hci_dev_do_close(struct hci_dev *hdev) +{ + //if (hdev->flush) + // hdev->flush(hdev); + /* After this point our queues are empty + * and no tasks are scheduled. */ + //hdev->close(hdev); + /* Clear flags */ + hdev->flags = 0; + return 0; +} + +static int hci_dev_close(__u16 dev) +{ + struct hci_dev *hdev; + int err; + hdev = hci_dev_get(dev); + if (!hdev) { + AICBT_ERR("%s: failed to get hci dev[Null]", __func__); + return -ENODEV; + } + + err = hci_dev_do_close(hdev); + + return err; +} + +#if CONFIG_BLUEDROID +static struct hci_dev *hci_alloc_dev(void) +{ + struct hci_dev *hdev; + + hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); + if (!hdev) + return NULL; + + return hdev; +} + +/* Free HCI device */ +static void hci_free_dev(struct hci_dev *hdev) +{ + kfree(hdev); +} + +/* Register HCI device */ +static int hci_register_dev(struct hci_dev *hdev) +{ + int i, id; + + AICBT_DBG("%s: %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); + /* Do not allow HCI_AMP devices to register at index 0, + * so the index can be used as the AMP controller ID. + */ + id = (hdev->dev_type == HCI_BREDR) ? 0 : 1; + + write_lock(&hci_dev_lock); + + sprintf(hdev->name, "hci%d", id); + hdev->id = id; + hdev->flags = 0; + hdev->dev_flags = 0; + mutex_init(&hdev->lock); + + AICBT_DBG("%s: id %d, name %s", __func__, hdev->id, hdev->name); + + + for (i = 0; i < NUM_REASSEMBLY; i++) + hdev->reassembly[i] = NULL; + + memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); + atomic_set(&hdev->promisc, 0); + + if (ghdev) { + write_unlock(&hci_dev_lock); + AICBT_ERR("%s: Hci device has been registered already", __func__); + return -1; + } else + ghdev = hdev; + + write_unlock(&hci_dev_lock); + + return id; +} + +/* Unregister HCI device */ +static void hci_unregister_dev(struct hci_dev *hdev) +{ + int i; + + AICBT_DBG("%s: hdev %p name %s bus %d", __func__, hdev, hdev->name, hdev->bus); + set_bit(HCI_UNREGISTER, &hdev->dev_flags); + + write_lock(&hci_dev_lock); + ghdev = NULL; + write_unlock(&hci_dev_lock); + + hci_dev_do_close(hdev); + for (i = 0; i < NUM_REASSEMBLY; i++) + kfree_skb(hdev->reassembly[i]); +} + +static void hci_send_to_stack(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct sk_buff *aic_skb_copy = NULL; + + //AICBT_DBG("%s", __func__); + + if (!hdev) { + AICBT_ERR("%s: Frame for unknown HCI device", __func__); + return; + } + + if (!test_bit(HCI_RUNNING, &hdev->flags)) { + AICBT_ERR("%s: HCI not running", __func__); + return; + } + + aic_skb_copy = pskb_copy(skb, GFP_ATOMIC); + if (!aic_skb_copy) { + AICBT_ERR("%s: Copy skb error", __func__); + return; + } + + memcpy(skb_push(aic_skb_copy, 1), &bt_cb(skb)->pkt_type, 1); + aic_enqueue(aic_skb_copy); + + /* Make sure bt char device existing before wakeup read queue */ + hdev = hci_dev_get(0); + if (hdev) { + //AICBT_DBG("%s: Try to wakeup read queue", __func__); + AICBT_DBG("%s", __func__); + wake_up_interruptible(&btchr_read_wait); + } + + + return; +} + +/* Receive frame from HCI drivers */ +static int hci_recv_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *) skb->dev; + + if (!hdev || + (!test_bit(HCI_UP, &hdev->flags) && !test_bit(HCI_INIT, &hdev->flags))) { + kfree_skb(skb); + return -ENXIO; + } + + /* Incomming skb */ + bt_cb(skb)->incoming = 1; + + /* Time stamp */ + __net_timestamp(skb); + + if (atomic_read(&hdev->promisc)) { +#ifdef CONFIG_SCO_OVER_HCI + if(bt_cb(skb)->pkt_type == HCI_SCODATA_PKT){ + hci_send_to_alsa_ringbuffer(hdev, skb); + }else{ + if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ + if(bypass_event(skb)){ + kfree_skb(skb); + return 0; + } + } + hci_send_to_stack(hdev, skb); + } +#else + if(bt_cb(skb)->pkt_type == HCI_EVENT_PKT){ + if(bypass_event(skb)){ + kfree_skb(skb); + return 0; + } + } + /* Send copy to the sockets */ + hci_send_to_stack(hdev, skb); +#endif + + } + + kfree_skb(skb); + return 0; +} + + + +static int hci_reassembly(struct hci_dev *hdev, int type, void *data, + int count, __u8 index) +{ + int len = 0; + int hlen = 0; + int remain = count; + struct sk_buff *skb; + struct bt_skb_cb *scb; + + //AICBT_DBG("%s", __func__); + + if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || + index >= NUM_REASSEMBLY) + return -EILSEQ; + + skb = hdev->reassembly[index]; + + if (!skb) { + switch (type) { + case HCI_ACLDATA_PKT: + len = HCI_MAX_FRAME_SIZE; + hlen = HCI_ACL_HDR_SIZE; + break; + case HCI_EVENT_PKT: + len = HCI_MAX_EVENT_SIZE; + hlen = HCI_EVENT_HDR_SIZE; + break; + case HCI_SCODATA_PKT: + len = HCI_MAX_SCO_SIZE; + hlen = HCI_SCO_HDR_SIZE; + break; + } + + skb = bt_skb_alloc(len, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + scb = (void *) skb->cb; + scb->expect = hlen; + scb->pkt_type = type; + + skb->dev = (void *) hdev; + hdev->reassembly[index] = skb; + } + + while (count) { + scb = (void *) skb->cb; + len = min_t(uint, scb->expect, count); + + memcpy(skb_put(skb, len), data, len); + + count -= len; + data += len; + scb->expect -= len; + remain = count; + + switch (type) { + case HCI_EVENT_PKT: + if (skb->len == HCI_EVENT_HDR_SIZE) { + struct hci_event_hdr *h = hci_event_hdr(skb); + scb->expect = h->plen; + + if (skb_tailroom(skb) < scb->expect) { + kfree_skb(skb); + hdev->reassembly[index] = NULL; + return -ENOMEM; + } + } + break; + + case HCI_ACLDATA_PKT: + if (skb->len == HCI_ACL_HDR_SIZE) { + struct hci_acl_hdr *h = hci_acl_hdr(skb); + scb->expect = __le16_to_cpu(h->dlen); + + if (skb_tailroom(skb) < scb->expect) { + kfree_skb(skb); + hdev->reassembly[index] = NULL; + return -ENOMEM; + } + } + break; + + case HCI_SCODATA_PKT: + if (skb->len == HCI_SCO_HDR_SIZE) { + struct hci_sco_hdr *h = hci_sco_hdr(skb); + scb->expect = h->dlen; + + if (skb_tailroom(skb) < scb->expect) { + kfree_skb(skb); + hdev->reassembly[index] = NULL; + return -ENOMEM; + } + } + break; + } + + if (scb->expect == 0) { + /* Complete frame */ + if(HCI_ACLDATA_PKT == type) + print_acl(skb,0); + if(HCI_SCODATA_PKT == type) + print_sco(skb,0); + if(HCI_EVENT_PKT == type) + print_event(skb); + + bt_cb(skb)->pkt_type = type; + hci_recv_frame(skb); + + hdev->reassembly[index] = NULL; + return remain; + } + } + + return remain; +} + +int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) +{ + int rem = 0; + + if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) + return -EILSEQ; + + while (count) { + rem = hci_reassembly(hdev, type, data, count, type - 1); + if (rem < 0) + return rem; + + data += (count - rem); + count = rem; + } + + return rem; +} +#endif //CONFIG_BLUEDROID + +static int btchr_open(struct inode *inode_p, struct file *file_p) +{ + struct btusb_data *data; + struct hci_dev *hdev; + + AICBT_DBG("%s: BT sdio char device is opening", __func__); + /* Not open unless wanna tracing log */ + /* trace_printk("%s: open....\n", __func__); */ + + hdev = hci_dev_get(0); + if (!hdev) { + AICBT_DBG("%s: Failed to get hci dev[NULL]", __func__); + return -ENODEV; + } + data = GET_DRV_DATA(hdev); + + atomic_inc(&hdev->promisc); + /* + * As bt device is not re-opened when hotplugged out, we cannot + * trust on file's private data(may be null) when other file ops + * are invoked. + */ + file_p->private_data = data; + + mutex_lock(&btchr_mutex); + hci_dev_open(0); + mutex_unlock(&btchr_mutex); + + aic_clear_queue(); + return nonseekable_open(inode_p, file_p); +} + +static int btchr_close(struct inode *inode_p, struct file *file_p) +{ + struct btusb_data *data; + struct hci_dev *hdev; + + AICBT_INFO("%s: BT sdio char device is closing", __func__); + /* Not open unless wanna tracing log */ + /* trace_printk("%s: close....\n", __func__); */ + + data = file_p->private_data; + file_p->private_data = NULL; + +#if CONFIG_BLUEDROID + /* + * If the upper layer closes bt char interfaces, no reset + * action required even bt device hotplugged out. + */ + bt_reset = 0; +#endif + + hdev = hci_dev_get(0); + if (hdev) { + atomic_set(&hdev->promisc, 0); + mutex_lock(&btchr_mutex); + hci_dev_close(0); + mutex_unlock(&btchr_mutex); + } + + return 0; +} + +void bt_data_dump(char* tag, void* data, unsigned long len){ + unsigned long i = 0; + uint8_t* data_ = (uint8_t* )data; + + printk("%s %s len:(%lu)\r\n", __func__, tag, len); + + for (i = 0; i < len; i += 16){ + printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", + data_[0 + i], + data_[1 + i], + data_[2 + i], + data_[3 + i], + data_[4 + i], + data_[5 + i], + data_[6 + i], + data_[7 + i], + data_[8 + i], + data_[9 + i], + data_[10 + i], + data_[11 + i], + data_[12 + i], + data_[13 + i], + data_[14 + i], + data_[15 + i]); + } + +} + +static ssize_t btchr_read(struct file *file_p, + char __user *buf_p, + size_t count, + loff_t *pos_p) +{ + struct hci_dev *hdev; + struct sk_buff *skb; + ssize_t ret = 0; + + while (count) { +#if 1 + hdev = hci_dev_get(0); + if (!hdev) { + /* + * Note: Only when BT device hotplugged out, we wil get + * into such situation. In order to keep the upper layer + * stack alive (blocking the read), we should never return + * EFAULT or break the loop. + */ + AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); + } +#endif + ret = wait_event_interruptible(btchr_read_wait, !is_queue_empty()); + if (ret < 0) { + AICBT_ERR("%s: wait event is signaled %d", __func__, (int)ret); + break; + } + + skb = aic_dequeue_try(count); + //bt_data_dump("btchr_read", skb->data, skb->len); + //printk("btchr_read \n"); + if (skb) { + ret = sdio_put_user(skb, buf_p, count); + if (ret < 0) + AICBT_ERR("%s: Failed to put data to user space", __func__); + kfree_skb(skb); + break; + } + } + + return ret; +} + +#ifdef CONFIG_SUPPORT_VENDOR_APCF +void btchr_external_write(char* buff, int len){ + struct hci_dev *hdev; + struct sk_buff *skb; + int i; + struct btusb_data *data; + + AICBT_INFO("%s \r\n", __func__); + for(i=0;idev = (void *)hdev; + memcpy((__u8 *)skb->data,(__u8 *)buff,len); + skb_put(skb, len); + bt_cb(skb)->pkt_type = *((__u8 *)skb->data); + skb_pull(skb, 1); + data->hdev->send(skb); +} + +EXPORT_SYMBOL(btchr_external_write); +#endif //CONFIG_SUPPORT_VENDOR_APCF + +//extern struct rwnx_plat *g_rwnx_plat; +static ssize_t btchr_write(struct file *file_p, + const char __user *buf_p, + size_t count, + loff_t *pos_p) +{ + struct btusb_data *data = file_p->private_data; + struct hci_dev *hdev; + struct sk_buff *skb; + int err=0; + + AICBT_DBG("%s", __func__); + + hdev = hci_dev_get(0); + if (!hdev) { + AICBT_WARN("%s: Failed to get hci dev[Null]", __func__); + /* + * Note: we bypass the data from the upper layer if bt device + * is hotplugged out. Fortunatelly, H4 or H5 HCI stack does + * NOT check btchr_write's return value. However, returning + * count instead of EFAULT is preferable. + */ + /* return -EFAULT; */ + return count; + } + +#if 0 + /* Never trust on btusb_data, as bt device may be hotplugged out */ + data = GET_DRV_DATA(hdev); + if (!data) { + AICBT_WARN("%s: Failed to get bt usb driver data[Null]", __func__); + return count; + } +#endif + + if (count > HCI_MAX_FRAME_SIZE) + return -EINVAL; + + skb = bt_skb_alloc(count, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + skb_reserve(skb, -1); // Add this line + + if (copy_from_user(skb_put(skb, count), buf_p, count)) { + AICBT_ERR("%s: Failed to get data from user space", __func__); + kfree_skb(skb); + return -EFAULT; + } + + skb->dev = (void *)hdev; + bt_cb(skb)->pkt_type = *((__u8 *)skb->data); + //skb_pull(skb, 1); + //data->hdev->send(skb); + + //bt_data_dump("btwrite", skb->data, skb->len); + err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len, skb); + if(err<0){ + printk("%s rwnx_sdio_bt_send_req error %d",__func__,err); + } + + kfree_skb(skb); + return count; +} + +static unsigned int btchr_poll(struct file *file_p, poll_table *wait) +{ + struct btusb_data *data = file_p->private_data; + struct hci_dev *hdev; + + //AICBT_DBG("%s: BT sdio char device is polling", __func__); + + /*if(!bt_char_dev_registered) { + AICBT_ERR("%s: char device has not registered!", __func__); + return POLLERR | POLLHUP; + }*/ + //printk("poll wait\n"); + poll_wait(file_p, &btchr_read_wait, wait); + //printk("poll out\n"); + + hdev = hci_dev_get(0); + if (!hdev) { + AICBT_ERR("%s: Failed to get hci dev[Null]", __func__); + //mdelay(URB_CANCELING_DELAY_MS); + return POLLERR | POLLHUP; + return POLLOUT | POLLWRNORM; + } + +#if 0 + /* Never trust on btusb_data, as bt device may be hotplugged out */ + data = GET_DRV_DATA(hdev); + if (!data) { + /* + * When bt device is hotplugged out, btusb_data will + * be freed in disconnect. + */ + AICBT_ERR("%s: Failed to get bt sdio driver data[Null]", __func__); + mdelay(URB_CANCELING_DELAY_MS); + return POLLOUT | POLLWRNORM; + } +#endif + + if (!is_queue_empty()) + return POLLIN | POLLRDNORM; + + return POLLOUT | POLLWRNORM; +} +static long btchr_ioctl(struct file *file_p,unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct hci_dev *hdev; + struct btusb_data *data; + //firmware_info *fw_info; + + /*if(!bt_char_dev_registered) { + return -ENODEV; + }*/ + + printk("%s cmd support %d \n",__func__,cmd); + +#if 1 + if(check_set_dlfw_state_value(1) != 1) { + AICBT_ERR("%s bt controller is disconnecting!", __func__); + return 0; + } + + hdev = hci_dev_get(0); + if(!hdev) { + AICBT_ERR("%s device is NULL!", __func__); + set_dlfw_state_value(0); + return 0; + } + //data = GET_DRV_DATA(hdev); + //fw_info = data->fw_info; + + AICBT_INFO(" btchr_ioctl DOWN_FW_CFG with Cmd:%d",cmd); + switch (cmd) { + case DOWN_FW_CFG: + AICBT_INFO(" btchr_ioctl DOWN_FW_CFG"); + /*ret = usb_autopm_get_interface(data->intf); + if (ret < 0){ + goto failed; + }*/ + + //ret = download_patch(fw_info,1); + /*usb_autopm_put_interface(data->intf); + if(ret < 0){ + AICBT_ERR("%s:Failed in download_patch with ret:%d",__func__,ret); + goto failed; + } + + ret = hdev->open(hdev); + if(ret < 0){ + AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); + goto failed; + }*/ + set_bit(HCI_UP, &hdev->flags); + set_dlfw_state_value(0); + wake_up_interruptible(&bt_dlfw_wait); + return 1; + case DWFW_CMPLT: + AICBT_INFO(" btchr_ioctl DWFW_CMPLT"); +#if 1 + case SET_ISO_CFG: + AICBT_INFO("btchr_ioctl SET_ISO_CFG"); + if(copy_from_user(&(hdev->voice_setting), (__u16*)arg, sizeof(__u16))){ + AICBT_INFO(" voice settings err"); + } + //hdev->voice_setting = *(uint16_t*)arg; + AICBT_INFO(" voice settings = %d", hdev->voice_setting); + //return 1; +#endif + case GET_USB_INFO: + //ret = download_patch(fw_info,1); + AICBT_INFO(" btchr_ioctl GET_USB_INFO"); + /*ret = hdev->open(hdev); + if(ret < 0){ + AICBT_ERR("%s:Failed in hdev->open(hdev):%d",__func__,ret); + //goto done; + }*/ + set_bit(HCI_UP, &hdev->flags); + set_dlfw_state_value(0); + wake_up_interruptible(&bt_dlfw_wait); + return 1; + case RESET_CONTROLLER: + AICBT_INFO(" btchr_ioctl RESET_CONTROLLER"); + //reset_controller(fw_info); + return 1; + default: + AICBT_ERR("%s:Failed with wrong Cmd:%d",__func__,cmd); + goto failed; + } + failed: + set_dlfw_state_value(0); + wake_up_interruptible(&bt_dlfw_wait); + return ret; +#endif +} + +#ifdef CONFIG_PLATFORM_UBUNTU//AIDEN +typedef u32 compat_uptr_t; +static inline void __user *compat_ptr(compat_uptr_t uptr) +{ + return (void __user *)(unsigned long)uptr; +} +#endif + +#ifdef CONFIG_COMPAT +static long compat_btchr_ioctl (struct file *filp, unsigned int cmd, unsigned long arg) +{ + AICBT_DBG("%s: enter",__func__); + return btchr_ioctl(filp, cmd, (unsigned long) compat_ptr(arg)); +} +#endif +static struct file_operations bt_chrdev_ops = { + open : btchr_open, + release : btchr_close, + read : btchr_read, + write : btchr_write, + poll : btchr_poll, + unlocked_ioctl : btchr_ioctl, +#ifdef CONFIG_COMPAT + compat_ioctl : compat_btchr_ioctl, +#endif +}; + +int btchr_init() +{ + int res = 0; + struct device *dev; + + AICBT_INFO("Register sdio char device interface for BT driver"); + /* + * btchr mutex is used to sync between + * 1) downloading patch and opening bt char driver + * 2) the file operations of bt char driver + */ + mutex_init(&btchr_mutex); + + skb_queue_head_init(&btchr_readq); + init_waitqueue_head(&btchr_read_wait); + init_waitqueue_head(&bt_dlfw_wait); + + bt_char_class = class_create(THIS_MODULE, BT_CHAR_DEVICE_NAME); + if (IS_ERR(bt_char_class)) { + AICBT_ERR("Failed to create bt char class"); + return PTR_ERR(bt_char_class); + } + + res = alloc_chrdev_region(&bt_devid, 0, 1, BT_CHAR_DEVICE_NAME); + if (res < 0) { + AICBT_ERR("Failed to allocate bt char device"); + goto err_alloc; + } + + dev = device_create(bt_char_class, NULL, bt_devid, NULL, BT_CHAR_DEVICE_NAME); + if (IS_ERR(dev)) { + AICBT_ERR("Failed to create bt char device"); + res = PTR_ERR(dev); + goto err_create; + } + + cdev_init(&bt_char_dev, &bt_chrdev_ops); + res = cdev_add(&bt_char_dev, bt_devid, 1); + if (res < 0) { + AICBT_ERR("Failed to add bt char device"); + goto err_add; + } + + return 0; + +err_add: + device_destroy(bt_char_class, bt_devid); +err_create: + unregister_chrdev_region(bt_devid, 1); +err_alloc: + class_destroy(bt_char_class); + return res; +} + +void btchr_exit(void) +{ + AICBT_INFO("Unregister sdio char device interface for BT driver"); + + device_destroy(bt_char_class, bt_devid); + cdev_del(&bt_char_dev); + unregister_chrdev_region(bt_devid, 1); + class_destroy(bt_char_class); + + return; +} + +int hdev_init(void) +{ + struct hci_dev *hdev; + int err=0; + hdev = hci_alloc_dev(); + + err = hci_register_dev(hdev); + if (err < 0) { + hci_free_dev(hdev); + hdev = NULL; + return err; + } + + spin_lock_init(&queue_lock); + + return 0; +} + +void hdev_exit(void) +{ + struct hci_dev *hdev; + hdev = ghdev; + hci_unregister_dev(hdev); + hci_free_dev(hdev); +} + diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_btsdio.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_btsdio.h new file mode 100755 index 000000000..719c2c6bc --- /dev/null +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_btsdio.h @@ -0,0 +1,549 @@ +#ifndef _AICWF_SDIO_BT_H_ +#define _AICWF_SDIO_BT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#ifdef CONFIG_PLATFORM_UBUNTU +#define CONFIG_BLUEDROID 1 /* bleuz 0, bluedroid 1 */ +#else +#define CONFIG_BLUEDROID 1 /* bleuz 0, bluedroid 1 */ +#endif +/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */ +#define HCI_VERSION_CODE LINUX_VERSION_CODE + + +#define PRINT_CMD_EVENT 1 +#define PRINT_ACL_DATA 1 +#define PRINT_SCO_DATA 1 + +#define AICBT_DBG_FLAG 1 + +#if AICBT_DBG_FLAG +#define AICBT_DBG(fmt, arg...) printk( "aic_btsdio: " fmt "\n" , ## arg) +#else +#define AICBT_DBG(fmt, arg...) +#endif + +#define AICBT_INFO(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) +#define AICBT_WARN(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) +#define AICBT_ERR(fmt, arg...) printk("aic_btsdio: " fmt "\n" , ## arg) + +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0) +#define GET_DRV_DATA(x) hci_get_drvdata(x) +#else +#define GET_DRV_DATA(x) x->driver_data +#endif + +struct btusb_data { + struct hci_dev *hdev; + //struct usb_device *udev; + //struct usb_interface *intf; + //struct usb_interface *isoc; + + spinlock_t lock; + + unsigned long flags; + + struct work_struct work; + struct work_struct waker; + + /*struct usb_anchor tx_anchor; + struct usb_anchor intr_anchor; + struct usb_anchor bulk_anchor; + struct usb_anchor isoc_anchor; + struct usb_anchor deferred;*/ + int tx_in_flight; + spinlock_t txlock; + +#if (CONFIG_BLUEDROID == 0) +#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + spinlock_t rxlock; + struct sk_buff *evt_skb; + struct sk_buff *acl_skb; + struct sk_buff *sco_skb; +#endif +#endif + + /*struct usb_endpoint_descriptor *intr_ep; + struct usb_endpoint_descriptor *bulk_tx_ep; + struct usb_endpoint_descriptor *bulk_rx_ep; + struct usb_endpoint_descriptor *isoc_tx_ep; + struct usb_endpoint_descriptor *isoc_rx_ep;*/ + + __u8 cmdreq_type; + + unsigned int sco_num; + int isoc_altsetting; + int suspend_count; + uint16_t sco_handle; + +#if (CONFIG_BLUEDROID == 0) +#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + int (*recv_bulk) (struct btusb_data * data, void *buffer, int count); +#endif +#endif + +//#ifdef CONFIG_HAS_EARLYSUSPEND +#if 0 + struct early_suspend early_suspend; +#else + struct notifier_block pm_notifier; + struct notifier_block reboot_notifier; +#endif + //firmware_info *fw_info; + +#ifdef CONFIG_SCO_OVER_HCI + AIC_sco_card_t *pSCOSnd; +#endif +}; + + + +#define QUEUE_SIZE 500 + +/*************************************** +** AicSemi - Integrate from bluetooth.h ** +*****************************************/ +/* Reserv for core and drivers use */ +#define BT_SKB_RESERVE 8 + +/* BD Address */ +typedef struct { + __u8 b[6]; +} __packed bdaddr_t; + +/* Skb helpers */ +struct bt_skb_cb { + __u8 pkt_type; + __u8 incoming; + __u16 expect; + __u16 tx_seq; + __u8 retries; + __u8 sar; + __u8 force_active; +}; + +#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) + + +/*********************************** +** AicSemi - Integrate from hci.h ** +***********************************/ +#define HCI_MAX_ACL_SIZE 1024 +#define HCI_MAX_SCO_SIZE 255 +#define HCI_MAX_EVENT_SIZE 260 +#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) + +/* HCI bus types */ +#define HCI_VIRTUAL 0 +#define HCI_USB 1 +#define HCI_PCCARD 2 +#define HCI_UART 3 +#define HCI_RS232 4 +#define HCI_PCI 5 +#define HCI_SDIO 6 + +/* HCI controller types */ +#define HCI_BREDR 0x00 +#define HCI_AMP 0x01 + +/* HCI device flags */ +enum { + HCI_UP, + HCI_INIT, + HCI_RUNNING, + + HCI_PSCAN, + HCI_ISCAN, + HCI_AUTH, + HCI_ENCRYPT, + HCI_INQUIRY, + + HCI_RAW, + + HCI_RESET, +}; + +/* + * BR/EDR and/or LE controller flags: the flags defined here should represent + * states from the controller. + */ +enum { + HCI_SETUP, + HCI_AUTO_OFF, + HCI_MGMT, + HCI_PAIRABLE, + HCI_SERVICE_CACHE, + HCI_LINK_KEYS, + HCI_DEBUG_KEYS, + HCI_UNREGISTER, + + HCI_LE_SCAN, + HCI_SSP_ENABLED, + HCI_HS_ENABLED, + HCI_LE_ENABLED, + HCI_CONNECTABLE, + HCI_DISCOVERABLE, + HCI_LINK_SECURITY, + HCI_PENDING_CLASS, +}; + +/* HCI data types */ +#define HCI_COMMAND_PKT 0x01 +#define HCI_ACLDATA_PKT 0x02 +#define HCI_SCODATA_PKT 0x03 +#define HCI_EVENT_PKT 0x04 +#define HCI_VENDOR_PKT 0xff + +#define HCI_MAX_NAME_LENGTH 248 +#define HCI_MAX_EIR_LENGTH 240 + +#define HCI_OP_READ_LOCAL_VERSION 0x1001 +struct hci_rp_read_local_version { + __u8 status; + __u8 hci_ver; + __le16 hci_rev; + __u8 lmp_ver; + __le16 manufacturer; + __le16 lmp_subver; +} __packed; + +#define HCI_EV_CMD_COMPLETE 0x0e +struct hci_ev_cmd_complete { + __u8 ncmd; + __le16 opcode; +} __packed; + +/* ---- HCI Packet structures ---- */ +#define HCI_COMMAND_HDR_SIZE 3 +#define HCI_EVENT_HDR_SIZE 2 +#define HCI_ACL_HDR_SIZE 4 +#define HCI_SCO_HDR_SIZE 3 + +struct hci_command_hdr { + __le16 opcode; /* OCF & OGF */ + __u8 plen; +} __packed; + +struct hci_event_hdr { + __u8 evt; + __u8 plen; +} __packed; + +struct hci_acl_hdr { + __le16 handle; /* Handle & Flags(PB, BC) */ + __le16 dlen; +} __packed; + +struct hci_sco_hdr { + __le16 handle; + __u8 dlen; +} __packed; + +static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) +{ + return (struct hci_event_hdr *) skb->data; +} + +static inline struct hci_acl_hdr *hci_acl_hdr(const struct sk_buff *skb) +{ + return (struct hci_acl_hdr *) skb->data; +} + +static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) +{ + return (struct hci_sco_hdr *) skb->data; +} + +/* ---- HCI Ioctl requests structures ---- */ +struct hci_dev_stats { + __u32 err_rx; + __u32 err_tx; + __u32 cmd_tx; + __u32 evt_rx; + __u32 acl_tx; + __u32 acl_rx; + __u32 sco_tx; + __u32 sco_rx; + __u32 byte_rx; + __u32 byte_tx; +}; +/* AicSemi - Integrate from hci.h end */ + +/***************************************** +** AicSemi - Integrate from hci_core.h ** +*****************************************/ +struct hci_conn_hash { + struct list_head list; + unsigned int acl_num; + unsigned int sco_num; + unsigned int le_num; +}; + +#define HCI_MAX_SHORT_NAME_LENGTH 10 + +#define NUM_REASSEMBLY 4 +struct hci_dev { + struct mutex lock; + + char name[8]; + unsigned long flags; + __u16 id; + __u8 bus; + __u8 dev_type; + + struct sk_buff *reassembly[NUM_REASSEMBLY]; + + struct hci_conn_hash conn_hash; + + struct hci_dev_stats stat; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) + atomic_t refcnt; + struct module *owner; + void *driver_data; +#endif + + atomic_t promisc; + + struct device *parent; + struct device dev; + + unsigned long dev_flags; + + int (*open)(struct hci_dev *hdev); + int (*close)(struct hci_dev *hdev); + int (*flush)(struct hci_dev *hdev); + int (*send)(struct sk_buff *skb); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) + void (*destruct)(struct hci_dev *hdev); +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 1) + __u16 voice_setting; +#endif + void (*notify)(struct hci_dev *hdev, unsigned int evt); + int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); + u8 *align_data; +}; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0) +static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) +{ + atomic_inc(&d->refcnt); + return d; +} + +static inline void __hci_dev_put(struct hci_dev *d) +{ + if (atomic_dec_and_test(&d->refcnt)) + d->destruct(d); +} +#endif + +static inline void *hci_get_drvdata(struct hci_dev *hdev) +{ + return dev_get_drvdata(&hdev->dev); +} + +static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) +{ + dev_set_drvdata(&hdev->dev, data); +} + +#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) + + +/* ---- HCI Packet structures ---- */ +#define HCI_COMMAND_HDR_SIZE 3 +#define HCI_EVENT_HDR_SIZE 2 +#define HCI_ACL_HDR_SIZE 4 +#define HCI_SCO_HDR_SIZE 3 + +/* ----- HCI Commands ---- */ +#define HCI_OP_INQUIRY 0x0401 +#define HCI_OP_INQUIRY_CANCEL 0x0402 +#define HCI_OP_EXIT_PERIODIC_INQ 0x0404 +#define HCI_OP_CREATE_CONN 0x0405 +#define HCI_OP_DISCONNECT 0x0406 +#define HCI_OP_ADD_SCO 0x0407 +#define HCI_OP_CREATE_CONN_CANCEL 0x0408 +#define HCI_OP_ACCEPT_CONN_REQ 0x0409 +#define HCI_OP_REJECT_CONN_REQ 0x040a +#define HCI_OP_LINK_KEY_REPLY 0x040b +#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c +#define HCI_OP_PIN_CODE_REPLY 0x040d +#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e +#define HCI_OP_CHANGE_CONN_PTYPE 0x040f +#define HCI_OP_AUTH_REQUESTED 0x0411 +#define HCI_OP_SET_CONN_ENCRYPT 0x0413 +#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415 +#define HCI_OP_REMOTE_NAME_REQ 0x0419 +#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a +#define HCI_OP_READ_REMOTE_FEATURES 0x041b +#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c +#define HCI_OP_READ_REMOTE_VERSION 0x041d +#define HCI_OP_SETUP_SYNC_CONN 0x0428 +#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 +#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a +#define HCI_OP_SNIFF_MODE 0x0803 +#define HCI_OP_EXIT_SNIFF_MODE 0x0804 +#define HCI_OP_ROLE_DISCOVERY 0x0809 +#define HCI_OP_SWITCH_ROLE 0x080b +#define HCI_OP_READ_LINK_POLICY 0x080c +#define HCI_OP_WRITE_LINK_POLICY 0x080d +#define HCI_OP_READ_DEF_LINK_POLICY 0x080e +#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f +#define HCI_OP_SNIFF_SUBRATE 0x0811 +#define HCI_OP_Write_Link_Policy_Settings 0x080d +#define HCI_OP_SET_EVENT_MASK 0x0c01 +#define HCI_OP_RESET 0x0c03 +#define HCI_OP_SET_EVENT_FLT 0x0c05 +#define HCI_OP_Write_Extended_Inquiry_Response 0x0c52 +#define HCI_OP_Write_Simple_Pairing_Mode 0x0c56 +#define HCI_OP_Read_Buffer_Size 0x1005 +#define HCI_OP_Host_Buffer_Size 0x0c33 +#define HCI_OP_Read_Local_Version_Information 0x1001 +#define HCI_OP_Read_BD_ADDR 0x1009 +#define HCI_OP_Read_Local_Supported_Commands 0x1002 +#define HCI_OP_Write_Scan_Enable 0x0c1a +#define HCI_OP_Write_Current_IAC_LAP 0x0c3a +#define HCI_OP_Write_Inquiry_Scan_Activity 0x0c1e +#define HCI_OP_Write_Class_of_Device 0x0c24 +#define HCI_OP_LE_Rand 0x2018 +#define HCI_OP_LE_Set_Random_Address 0x2005 +#define HCI_OP_LE_Set_Extended_Scan_Enable 0x2042 +#define HCI_OP_LE_Set_Extended_Scan_Parameters 0x2041 +#define HCI_OP_Set_Event_Filter 0x0c05 +#define HCI_OP_Write_Voice_Setting 0x0c26 +#define HCI_OP_Change_Local_Name 0x0c13 +#define HCI_OP_Read_Local_Name 0x0c14 +#define HCI_OP_Wirte_Page_Timeout 0x0c18 +#define HCI_OP_LE_Clear_Resolving_List 0x0c29 +#define HCI_OP_LE_Set_Addres_Resolution_Enable_Command 0x0c2e +#define HCI_OP_Write_Inquiry_mode 0x0c45 +#define HCI_OP_Write_Page_Scan_Type 0x0c47 +#define HCI_OP_Write_Inquiry_Scan_Type 0x0c43 + +#define HCI_OP_Delete_Stored_Link_Key 0x0c12 +#define HCI_OP_LE_Read_Local_Resolvable_Address 0x202d +#define HCI_OP_LE_Extended_Create_Connection 0x2043 +#define HCI_OP_Read_Remote_Version_Information 0x041d +#define HCI_OP_LE_Start_Encryption 0x2019 +#define HCI_OP_LE_Add_Device_to_Resolving_List 0x2027 +#define HCI_OP_LE_Set_Privacy_Mode 0x204e +#define HCI_OP_LE_Connection_Update 0x2013 + +/* ----- HCI events---- */ +#define HCI_OP_DISCONNECT 0x0406 +#define HCI_EV_INQUIRY_COMPLETE 0x01 +#define HCI_EV_INQUIRY_RESULT 0x02 +#define HCI_EV_CONN_COMPLETE 0x03 +#define HCI_EV_CONN_REQUEST 0x04 +#define HCI_EV_DISCONN_COMPLETE 0x05 +#define HCI_EV_AUTH_COMPLETE 0x06 +#define HCI_EV_REMOTE_NAME 0x07 +#define HCI_EV_ENCRYPT_CHANGE 0x08 +#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09 + +#define HCI_EV_REMOTE_FEATURES 0x0b +#define HCI_EV_REMOTE_VERSION 0x0c +#define HCI_EV_QOS_SETUP_COMPLETE 0x0d +#define HCI_EV_CMD_COMPLETE 0x0e +#define HCI_EV_CMD_STATUS 0x0f + +#define HCI_EV_ROLE_CHANGE 0x12 +#define HCI_EV_NUM_COMP_PKTS 0x13 +#define HCI_EV_MODE_CHANGE 0x14 +#define HCI_EV_PIN_CODE_REQ 0x16 +#define HCI_EV_LINK_KEY_REQ 0x17 +#define HCI_EV_LINK_KEY_NOTIFY 0x18 +#define HCI_EV_CLOCK_OFFSET 0x1c +#define HCI_EV_PKT_TYPE_CHANGE 0x1d +#define HCI_EV_PSCAN_REP_MODE 0x20 + +#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 +#define HCI_EV_REMOTE_EXT_FEATURES 0x23 +#define HCI_EV_SYNC_CONN_COMPLETE 0x2c +#define HCI_EV_SYNC_CONN_CHANGED 0x2d +#define HCI_EV_SNIFF_SUBRATE 0x2e +#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f +#define HCI_EV_IO_CAPA_REQUEST 0x31 +#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 +#define HCI_EV_REMOTE_HOST_FEATURES 0x3d +#define HCI_EV_LE_Meta 0x3e + +/* ULP Event sub code */ +#define HCI_BLE_CONN_COMPLETE_EVT 0x01 +#define HCI_BLE_ADV_PKT_RPT_EVT 0x02 +#define HCI_BLE_LL_CONN_PARAM_UPD_EVT 0x03 +#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04 +#define HCI_BLE_LTK_REQ_EVT 0x05 +#define HCI_BLE_RC_PARAM_REQ_EVT 0x06 +#define HCI_BLE_DATA_LENGTH_CHANGE_EVT 0x07 +#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT 0x0a +#define HCI_BLE_DIRECT_ADV_EVT 0x0b +#define HCI_BLE_PHY_UPDATE_COMPLETE_EVT 0x0c +#define HCI_LE_EXTENDED_ADVERTISING_REPORT_EVT 0x0D +#define HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT 0x0E +#define HCI_BLE_PERIODIC_ADV_REPORT_EVT 0x0F +#define HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT 0x10 +#define HCI_BLE_SCAN_TIMEOUT_EVT 0x11 +#define HCI_LE_ADVERTISING_SET_TERMINATED_EVT 0x12 +#define HCI_BLE_SCAN_REQ_RX_EVT 0x13 +#define HCI_BLE_CIS_EST_EVT 0x19 +#define HCI_BLE_CIS_REQ_EVT 0x1a +#define HCI_BLE_CREATE_BIG_CPL_EVT 0x1b +#define HCI_BLE_TERM_BIG_CPL_EVT 0x1c +#define HCI_BLE_BIG_SYNC_EST_EVT 0x1d +#define HCI_BLE_BIG_SYNC_LOST_EVT 0x1e +#define HCI_BLE_REQ_PEER_SCA_CPL_EVT 0x1f + +#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ + +#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) //MAC's OFFSET in config/efuse for aic generation 1~2 bluetooth chip +#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) //MAC's OFFSET in config/efuse for aic generation 3+ bluetooth chip + +//Define ioctl cmd the same as HCIDEVUP in the kernel +#define DOWN_FW_CFG _IOW('E', 176, int) +//#ifdef CONFIG_SCO_OVER_HCI +//#define SET_ISO_CFG _IOW('H', 202, int) +//#else +#define SET_ISO_CFG _IOW('E', 177, int) +//#endif +#define RESET_CONTROLLER _IOW('E', 178, int) +#define DWFW_CMPLT _IOW('E', 179, int) + +#define GET_USB_INFO _IOR('E', 180, int) + +void bt_data_dump(char* tag, void* data, unsigned long len); +int aic_enqueue(struct sk_buff *skb); +int aic_queue_cnt(void); +int bt_sdio_recv(u8 *data,u32 data_len); + + +int btchr_init(void); +void btchr_exit(void); +int hdev_init(void); +void hdev_exit(void); + + +struct hci_dev *hci_dev_get(int index); +int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); + +#endif//_AICWF_SDIO_BT_H_ + diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_priv_cmd.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_priv_cmd.c new file mode 100755 index 000000000..386a2d5c0 --- /dev/null +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_priv_cmd.c @@ -0,0 +1,1776 @@ +/** + ****************************************************************************** + * + * @file aic_priv_cmd.c + * + * @brief Entry point of the AIC driver + * + * Copyright (C) Aicsemi 2018-2024 + * + ****************************************************************************** + */ + +#include +#include +#include "rwnx_defs.h" +#include "rwnx_msg_tx.h" +#include "rwnx_debugfs.h" +#include "rwnx_main.h" +#include "aicwf_sdio.h" +#include "aic_priv_cmd.h" + +extern int testmode; +static void print_help(const char *cmd); +struct dbg_rftest_cmd_cfm cfm = {{0,}}; + +#ifdef CONFIG_RFTEST +enum { + SET_TX, + SET_TXSTOP, + SET_TXTONE, + SET_RX, + GET_RX_RESULT, + SET_RXSTOP, + SET_RX_METER, + SET_POWER, + SET_XTAL_CAP, + SET_XTAL_CAP_FINE, + GET_EFUSE_BLOCK, + SET_FREQ_CAL, + SET_FREQ_CAL_FINE, + GET_FREQ_CAL, + SET_MAC_ADDR, + GET_MAC_ADDR, + SET_BT_MAC_ADDR, + GET_BT_MAC_ADDR, + SET_VENDOR_INFO, + GET_VENDOR_INFO, + RDWR_PWRMM, + RDWR_PWRIDX, + RDWR_PWRLVL = RDWR_PWRIDX, + RDWR_PWROFST, + RDWR_DRVIBIT, + RDWR_EFUSE_PWROFST, + RDWR_EFUSE_DRVIBIT, + SET_PAPR, + SET_CAL_XTAL, + GET_CAL_XTAL_RES, + SET_COB_CAL, + GET_COB_CAL_RES, + RDWR_EFUSE_USRDATA, + SET_NOTCH, + RDWR_PWROFSTFINE, + RDWR_EFUSE_PWROFSTFINE, + RDWR_EFUSE_SDIOCFG, + RDWR_EFUSE_USBVIDPID, + SET_SRRC, + SET_FSS, + RDWR_EFUSE_HE_OFF, + SET_USB_OFF, + SET_PLL_TEST, + +}; + +typedef struct { + u8_l chan; + u8_l bw; + u8_l mode; + u8_l rate; + u16_l length; + u16_l tx_intv_us; + s8_l max_pwr; +} cmd_rf_settx_t; + +typedef struct { + u8_l val; +} cmd_rf_setfreq_t; + +typedef struct { + u8_l chan; + u8_l bw; +} cmd_rf_rx_t; + +typedef struct { + u8_l block; +} cmd_rf_getefuse_t; + +typedef struct { + u8_l dutid; + u8_l chip_num; + u8_l dis_xtal; +} cmd_rf_setcobcal_t; + +typedef struct { + u16_l dut_rcv_golden_num; + u8_l golden_rcv_dut_num; + s8_l rssi_static; + s8_l snr_static; + s8_l dut_rssi_static; + u16_l reserved; +} cob_result_ptr_t; +#endif + +typedef struct +{ + u8_l func; + u8_l cnt; + u8_l reserved[2]; + u32_l usrdata[3]; // 3 words totally +} cmd_ef_usrdata_t; + +#define CMD_MAXARGS 10 +#define POWER_LEVEL_INVALID_VAL (127) + +#if 0//#include +#define isblank(c) ((c) == ' ' || (c) == '\t') +#define isascii(c) (((unsigned char)(c)) <= 0x7F) + +static int isdigit(unsigned char c) +{ + return ((c >= '0') && (c <='9')); +} + +static int isxdigit(unsigned char c) +{ + if ((c >= '0') && (c <='9')) + return 1; + if ((c >= 'a') && (c <='f')) + return 1; + if ((c >= 'A') && (c <='F')) + return 1; + return 0; +} + +static int islower(unsigned char c) +{ + return ((c >= 'a') && (c <='z')); +} + +static unsigned char toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} +#endif + +static int parse_line (char *line, char *argv[]) +{ + int nargs = 0; + + while (nargs < CMD_MAXARGS) { + /* skip any white space */ + while ((*line == ' ') || (*line == '\t')) { + ++line; + } + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = 0; + return nargs; + } + + /* Argument include space should be bracketed by quotation mark */ + if (*line == '\"') { + /* Skip quotation mark */ + line++; + + /* Begin of argument string */ + argv[nargs++] = line; + + /* Until end of argument */ + while (*line && (*line != '\"')) { + ++line; + } + } else { + argv[nargs++] = line; /* begin of argument string */ + + /* find end of string */ + while (*line && (*line != ' ') && (*line != '\t')) { + ++line; + } + } + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = 0; + return nargs; + } + + *line++ = '\0'; /* terminate current arg */ + } + + printk("** Too many args (max. %d) **\n", CMD_MAXARGS); + + return nargs; +} + +unsigned int command_strtoul(const char *cp, char **endp, unsigned int base) +{ + unsigned int result = 0, value, is_neg = 0; + + if (*cp == '0') { + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + base = 16; + cp++; + } + if (!base) { + base = 8; + } + } + if (!base) { + base = 10; + } + if (*cp == '-') { + is_neg = 1; + cp++; + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { + result = result * base + value; + cp++; + } + if (is_neg) + result = (unsigned int)((int)result * (-1)); + + if (endp) + *endp = (char *)cp; + return result; +} + +/* + * aic_priv_cmd handers. + */ +static int aic_priv_cmd_set_tx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_rf_settx_t settx_param; + + if (argc < 6) + return -EINVAL; + + settx_param.chan = command_strtoul(argv[1], NULL, 10); + settx_param.bw = command_strtoul(argv[2], NULL, 10); + settx_param.mode = command_strtoul(argv[3], NULL, 10); + settx_param.rate = command_strtoul(argv[4], NULL, 10); + settx_param.length = command_strtoul(argv[5], NULL, 10); + if (argc > 6) { + settx_param.tx_intv_us = command_strtoul(argv[6], NULL, 10); + } else { + settx_param.tx_intv_us = 10000; // set default val 10ms + } + settx_param.max_pwr = POWER_LEVEL_INVALID_VAL; + AICWFDBG(LOGINFO, "txparam:%d,%d,%d,%d,%d,%d\n", settx_param.chan, settx_param.bw, + settx_param.mode, settx_param.rate, settx_param.length, settx_param.tx_intv_us); + rwnx_send_rftest_req(rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); + return 0; +} + +static int aic_priv_cmd_set_txstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + rwnx_send_rftest_req(rwnx_hw, SET_TXSTOP, 0, NULL, NULL); + return 0; +} + +static int aic_priv_cmd_set_rx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_rf_rx_t setrx_param; + + if (argc < 3) { + return -EINVAL; + } + setrx_param.chan = command_strtoul(argv[1], NULL, 10); + setrx_param.bw = command_strtoul(argv[2], NULL, 10); + rwnx_send_rftest_req(rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); + return 0; +} + +static int aic_priv_cmd_get_rx_result (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + rwnx_send_rftest_req(rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); + memcpy(command, &cfm.rftest_result[0], 8); + return 8; +} + +static int aic_priv_cmd_set_rxstop (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + rwnx_send_rftest_req(rwnx_hw, SET_RXSTOP, 0, NULL, NULL); + return 0; +} + +static int aic_priv_cmd_set_tx_tone (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + u8_l buf[2]; + s8_l freq_ = 0; + + AICWFDBG(LOGINFO, "%s argc:%d\n", argv[0], argc); + if ((argc == 2) || (argc == 3)) { + AICWFDBG(LOGINFO, "argv 1:%s\n",argv[1]); + func = (u8_l)command_strtoul(argv[1], NULL, 16); + if (argc == 3) { + AICWFDBG(LOGINFO, "argv 2:%s\n",argv[2]); + freq_ = (u8_l)command_strtoul(argv[2], NULL, 10); + } else { + freq_ = 0; + }; + buf[0] = func; + buf[1] = (u8_l)freq_; + rwnx_send_rftest_req(rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); + } else { + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_set_rx_meter (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + s8_l freq = 0; + + freq = (int)command_strtoul(argv[1], NULL, 10); + rwnx_send_rftest_req(rwnx_hw, SET_RX_METER, sizeof(freq), (u8_l *)&freq, NULL); + return 0; +} + +static int aic_priv_cmd_set_set_power (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l ana_pwr; + u8_l dig_pwr; + u8_l pwr; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + if (dev->chipid == PRODUCT_ID_AIC8801) { + ana_pwr = command_strtoul(argv[1], NULL, 16); + dig_pwr = command_strtoul(argv[2], NULL, 16); + pwr = (ana_pwr << 4 | dig_pwr); + if (ana_pwr > 0xf || dig_pwr > 0xf) + return -EINVAL; + } else { + ana_pwr = command_strtoul(argv[1], NULL, 10); + pwr = ana_pwr; + if (ana_pwr > 0x1e) + return -EINVAL; + } + AICWFDBG(LOGINFO, "pwr =%x\r\n", pwr); + rwnx_send_rftest_req(rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); + return 0; +} + +static int aic_priv_cmd_set_xtal_cap (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l xtal_cap; + + if (argc < 2) + return -EINVAL; + + xtal_cap = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap); + rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_set_xtal_cap_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l xtal_cap_fine; + + if (argc < 2) + return -EINVAL; + + xtal_cap_fine = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap_fine); + rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_get_efuse_block (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_rf_getefuse_t getefuse_param; + + if (argc < 2) + return -EINVAL; + + getefuse_param.block = command_strtoul(argv[1], NULL, 10); + rwnx_send_rftest_req(rwnx_hw, GET_EFUSE_BLOCK, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); + AICWFDBG(LOGINFO, "get val=%x\r\n", cfm.rftest_result[0]); + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_set_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_rf_setfreq_t cmd_setfreq; + + if (argc < 2) + return -EINVAL; + + cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); + AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); + rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_set_freq_cal_fine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_rf_setfreq_t cmd_setfreq; + + if (argc < 2) + return -EINVAL; + + cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); + AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); + rwnx_send_rftest_req(rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_get_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l val; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + rwnx_send_rftest_req(rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm); + memcpy(command, &cfm.rftest_result[0], 4); + val = cfm.rftest_result[0]; + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { + AICWFDBG(LOGINFO, "cap=0x%x (remain:%x), cap_fine=%x (remain:%x)\n", + val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); + } else { + AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", val & 0xff, (val >> 8) & 0xff); + } + return 4; +} + +static int aic_priv_cmd_set_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l mac_addr[6]; + + if (argc < 7) + return -EINVAL; + + mac_addr[5] = command_strtoul(argv[1], NULL, 16); + mac_addr[4] = command_strtoul(argv[2], NULL, 16); + mac_addr[3] = command_strtoul(argv[3], NULL, 16); + mac_addr[2] = command_strtoul(argv[4], NULL, 16); + mac_addr[1] = command_strtoul(argv[5], NULL, 16); + mac_addr[0] = command_strtoul(argv[6], NULL, 16); + AICWFDBG(LOGINFO, "set macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); + rwnx_send_rftest_req(rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); + return 0; +} + +static int aic_priv_cmd_get_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u32_l addr0, addr1; + int rem_cnt = 0; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + rwnx_send_rftest_req(rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); + memcpy(command, &cfm.rftest_result[0], 8); + addr0 = cfm.rftest_result[0]; + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { + rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; + addr1 = cfm.rftest_result[1] & 0x0000FFFF; + AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); + } else { + addr1 = cfm.rftest_result[1]; + AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); + } + return 8; +} + +static int aic_priv_cmd_set_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l mac_addr[6]; + + if (argc < 7) + return -EINVAL; + + mac_addr[5] = command_strtoul(argv[1], NULL, 16); + mac_addr[4] = command_strtoul(argv[2], NULL, 16); + mac_addr[3] = command_strtoul(argv[3], NULL, 16); + mac_addr[2] = command_strtoul(argv[4], NULL, 16); + mac_addr[1] = command_strtoul(argv[5], NULL, 16); + mac_addr[0] = command_strtoul(argv[6], NULL, 16); + AICWFDBG(LOGINFO, "set bt macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); + rwnx_send_rftest_req(rwnx_hw, SET_BT_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); + return 0; +} + +static int aic_priv_cmd_get_bt_mac_addr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u32_l addr0, addr1; + int rem_cnt = 0; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + rwnx_send_rftest_req(rwnx_hw, GET_BT_MAC_ADDR, 0, NULL, &cfm); + memcpy(command, &cfm.rftest_result[0], 8); + addr0 = cfm.rftest_result[0]; + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { + rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; + addr1 = cfm.rftest_result[1] & 0x0000FFFF; + AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); + } else { + addr1 = cfm.rftest_result[1]; + AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); + } + return 8; +} + +static int aic_priv_cmd_set_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l vendor_info; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + vendor_info = command_strtoul(argv[1], NULL, 16); + AICWFDBG(LOGINFO, "set vendor info:%x\n", vendor_info); + rwnx_send_rftest_req(rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { + memcpy(command, &cfm.rftest_result[0], 2); + return 2; + } else { + memcpy(command, &cfm.rftest_result[0], 1); + return 1; + } + AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); +} + +static int aic_priv_cmd_get_vendor_info (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + rwnx_send_rftest_req(rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { + memcpy(command, &cfm.rftest_result[0], 2); + return 2; + } else { + memcpy(command, &cfm.rftest_result[0], 1); + return 1; + } + AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); +} + +static int aic_priv_cmd_rdwr_pwrmm (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + if (argc <= 1) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, 0, NULL, &cfm); + } else { // write + u8_l pwrmm = (u8_l)command_strtoul(argv[1], NULL, 16); + pwrmm = (pwrmm) ? 1 : 0; + AICWFDBG(LOGINFO, "set pwrmm = %x\r\n", pwrmm); + rwnx_send_rftest_req(rwnx_hw, RDWR_PWRMM, sizeof(pwrmm), (u8_l *)&pwrmm, &cfm); + } + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_rdwr_pwridx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + if (dev->chipid != PRODUCT_ID_AIC8801){ + AICWFDBG(LOGERROR, "unsupported cmd\n"); + return -EINVAL; + } + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, 0, NULL, &cfm); + } else if (func <= 2) { // write 2.4g/5g pwr idx + if (argc > 3) { + u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l pwridx = (u8_l)command_strtoul(argv[3], NULL, 10); + u8_l buf[3] = {func, type, pwridx}; + AICWFDBG(LOGINFO, "set pwridx:[%x][%x]=%x\r\n", func, type, pwridx); + rwnx_send_rftest_req(rwnx_hw, RDWR_PWRIDX, sizeof(buf), buf, &cfm); + } else { + return -EINVAL; + } + } else { + return -EINVAL; + } + memcpy(command, &cfm.rftest_result[0], 9); + return 9; +} + +static int aic_priv_cmd_rdwr_pwrlvl (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + if (dev->chipid == PRODUCT_ID_AIC8801){ + AICWFDBG(LOGERROR, "unsupported cmd\n"); + return -EINVAL; + } + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 0, NULL, &cfm); + } else if (func <= 2) { // write 2.4g/5g pwr lvl + if (argc > 4) { + u8_l grp = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l idx, size; + u8_l buf[14] = {func, grp,}; + if (argc > 12) { // set all grp + AICWFDBG(LOGINFO, "set pwrlvl %s:\n" + " [%x] =", (func == 1) ? "2.4g" : "5g", grp); + if (grp == 1) { // TXPWR_LVL_GRP_11N_11AC + size = 10; + } else { + size = 12; + } + for (idx = 0; idx < size; idx++) { + s8_l pwrlvl = (s8_l)command_strtoul(argv[3 + idx], NULL, 10); + buf[2 + idx] = (u8_l)pwrlvl; + if (idx && !(idx & 0x3)) { + AICWFDBG(LOGINFO, " "); + } + AICWFDBG(LOGINFO, " %2d", pwrlvl); + } + AICWFDBG(LOGINFO, "\n"); + size += 2; + } else { // set grp[idx] + u8_l idx = (u8_l)command_strtoul(argv[3], NULL, 10); + s8_l pwrlvl = (s8_l)command_strtoul(argv[4], NULL, 10); + buf[2] = idx; + buf[3] = (u8_l)pwrlvl; + size = 4; + AICWFDBG(LOGINFO, "set pwrlvl %s:\n" + " [%x][%d] = %d\n", (func == 1) ? "2.4g" : "5g", grp, idx, pwrlvl); + } + rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, size, buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + if(dev->chipid == PRODUCT_ID_AIC8800D80){ + memcpy(command, &cfm.rftest_result[0], 6 * 12); + return (6 * 12); + } else { + memcpy(command, &cfm.rftest_result[0], 3 * 12); + return (3 * 12); + } +} + +static int aic_priv_cmd_rdwr_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + int res_len = 0; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm); + } else if (func <= 2) { // write 2.4g/5g pwr ofst + if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80)) { + u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); + s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); + u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; + AICWFDBG(LOGINFO, "set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); + rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); + } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80)) { + u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); + s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); + u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; + AICWFDBG(LOGINFO, "set pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); + rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); + } else { + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 3 = 3 (2.4g) + res_len = 3; + } else if (dev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) + res_len = 3 * 3 + 3 * 6; + } else { + res_len = 3 + 4; + } + memcpy(command, &cfm.rftest_result[0], res_len); + return res_len; +} + +static int aic_priv_cmd_rdwr_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, 0, NULL, &cfm); + } else if (func <= 2) { // write 2.4g/5g pwr ofst + if (argc > 3) { + u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); + s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); + u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; + AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); + rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + + } + memcpy(command, &cfm.rftest_result[0], 7); + return 7; +} + +static int aic_priv_cmd_rdwr_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, 0, NULL, &cfm); + } else if (func == 1) { // write 2.4g pa drv_ibit + if (argc > 2) { + u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l buf[2] = {func, ibit}; + AICWFDBG(LOGINFO, "set drvibit:[%x]=%x\r\n", func, ibit); + rwnx_send_rftest_req(rwnx_hw, RDWR_DRVIBIT, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + memcpy(command, &cfm.rftest_result[0], 16); + return 16; +} + +static int aic_priv_cmd_rdwr_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + int res_len = 0; +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *dev = g_rwnx_plat->usbdev; +#endif + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm); + } else if (func <= 2) { // write 2.4g/5g pwr ofst + if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D80)) { + u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); + s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); + u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; + AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); + } else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D80)) { + u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); + s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); + u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; + AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 + res_len = 3 * 2; + } else if (dev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) + res_len = (3 * 3 + 3 * 6) * 2; + } else { // 7 = 3(2.4g) + 4(5g) + res_len = 3 + 4; + } + memcpy(command, &cfm.rftest_result[0], res_len); + return res_len; +} + +static int aic_priv_cmd_rdwr_efuse_pwrofstfine (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, 0, NULL, &cfm); + } else if (func <= 2) { // write 2.4g/5g pwr ofst + if (argc > 3) { + u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); + s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); + u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; + AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + memcpy(command, &cfm.rftest_result[0], 7); + return 7; +} + +static int aic_priv_cmd_rdwr_efuse_drvibit (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, 0, NULL, &cfm); + } else if (func == 1) { // write 2.4g pa drv_ibit + if (argc > 2) { + u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l buf[2] = {func, ibit}; + AICWFDBG(LOGINFO, "set efuse drvibit:[%x]=%x\r\n", func, ibit); + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_DRVIBIT, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_rdwr_efuse_usrdata (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_ef_usrdata_t cmd_ef_usrdata; + + if (argc <= 1) { // read all + cmd_ef_usrdata.func = 0; + cmd_ef_usrdata.cnt = 3; + } else if (argc >= 2) { // read/write + cmd_ef_usrdata.func = (u8_l)command_strtoul(argv[1], NULL, 10); + cmd_ef_usrdata.cnt = (u8_l)command_strtoul(argv[2], NULL, 10); + if (cmd_ef_usrdata.func == 1) { + int idx; + for (idx = 0; idx < cmd_ef_usrdata.cnt; idx++) { + cmd_ef_usrdata.usrdata[idx] = (u32_l)command_strtoul(argv[3 + idx], NULL, 16); + } + } + } else { + AICWFDBG(LOGERROR, "wrong argc: %x\n", argc); + return -EINVAL; + } + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USRDATA, sizeof(cmd_ef_usrdata), (u8_l *)&cmd_ef_usrdata, &cfm); + memcpy(command, &cfm.rftest_result[0], 12); + return 12; +} + +static int aic_priv_cmd_rdwr_efuse_sdiocfg (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, 0, NULL, &cfm); + } else if (func == 1) { // write sdiocfg + if (argc > 2) { + u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); + u8_l buf[2] = {func, ibit}; + AICWFDBG(LOGINFO, "set efuse sdiocfg:[%x]=%x\r\n", func, ibit); + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_SDIOCFG, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_rdwr_efuse_usbvidpid (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + AICWFDBG(LOGINFO, "read/write usb vid/pid into efuse\n"); + if (argc > 1) { + func = (u8_l)command_strtoul(argv[1], NULL, 16); + } + if (func == 0) { // read cur + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, 0, NULL, &cfm); + } else if (func == 1) { // write USB vid+pid + if (argc > 2) { + u32_l usb_id = (u32_l)command_strtoul(argv[2], NULL, 16); + u8_l buf[5] = {func, (u8_l)usb_id, (u8_l)(usb_id >> 8), (u8_l)(usb_id >> 16), (u8_l)(usb_id >> 24)}; + AICWFDBG(LOGINFO, "set efuse usb vid/pid:[%x]=%x\r\n", func, usb_id); + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_USBVIDPID, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong args\n"); + return -EINVAL; + } + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + memcpy(command, &cfm.rftest_result[0], 4); + return 4; +} + +static int aic_priv_cmd_rdwr_efuse_he_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + + func = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "set he off: %d\n", func); + if(func == 1) { + rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_HE_OFF, sizeof(func), (u8_l *)&func, &cfm); + AICWFDBG(LOGINFO, "he_off cfm: %d\n", cfm.rftest_result[0]); + memcpy(command, &cfm.rftest_result[0], 4); + return 4; + } + return 0; +} + +static int aic_priv_cmd_set_cal_xtal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + rwnx_send_rftest_req(rwnx_hw, SET_CAL_XTAL, 0, NULL, NULL); + return 0; +} + +static int aic_priv_cmd_get_cal_xtal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + rwnx_send_rftest_req(rwnx_hw, GET_CAL_XTAL_RES, 0, NULL, &cfm); + memcpy(command, &cfm.rftest_result[0], 4); + AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", cfm.rftest_result[0] & 0x0000ffff, (cfm.rftest_result[0] >> 16) & 0x0000ffff); + return 4; +} + +static int aic_priv_cmd_set_cob_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + cmd_rf_setcobcal_t setcob_cal; + + if (argc < 3) + return -EINVAL; + setcob_cal.dutid = command_strtoul(argv[1], NULL, 10); + setcob_cal.chip_num = command_strtoul(argv[2], NULL, 10); + setcob_cal.dis_xtal = command_strtoul(argv[3], NULL, 10); + rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); + return 0; +} + +static int aic_priv_cmd_get_cob_cal_res (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l state; + cob_result_ptr_t *cob_result_ptr; + + rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); + state = (cfm.rftest_result[0] >> 16) & 0x000000ff; + if (!state){ + AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", + cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); + cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); + AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", + cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, + cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); + memcpy(command, &cfm.rftest_result, 16); + return 16; + } else { + AICWFDBG(LOGERROR, "cob not idle\n"); + return -EINVAL; + } +} + +static int aic_priv_cmd_do_cob_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l state; + cmd_rf_setcobcal_t setcob_cal; + cob_result_ptr_t *cob_result_ptr; + + setcob_cal.dutid = 1; + setcob_cal.chip_num = 1; + setcob_cal.dis_xtal = 0; + if (argc > 1) + setcob_cal.dis_xtal = command_strtoul(argv[1], NULL, 10); + rwnx_send_rftest_req(rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); + msleep(2000); + rwnx_send_rftest_req(rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); + state = (cfm.rftest_result[0] >> 16) & 0x000000ff; + if (!state){ + AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", + cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); + cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); + AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", + cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, + cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); + memcpy(command, &cfm.rftest_result, 16); + return 16; + } else { + AICWFDBG(LOGERROR, "cob not idle\n"); + return -EINVAL; + } +} + +static int aic_priv_cmd_set_papr (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + if (argc > 1) { + func = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "papr %d\r\n", func); + rwnx_send_rftest_req(rwnx_hw, SET_PAPR, sizeof(func), (u8_l *)&func, NULL); + } else { + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_set_notch (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + if (argc > 1) { + func = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "notch %d\r\n", func); + rwnx_send_rftest_req(rwnx_hw, SET_NOTCH, sizeof(func), (u8_l *)&func, NULL); + } else { + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_set_srrc (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + if (argc > 1) { + func = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "srrc %d\r\n", func); + rwnx_send_rftest_req(rwnx_hw, SET_SRRC, sizeof(func), (u8_l *)&func, NULL); + } else { + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_set_fss (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0; + if (argc > 1) { + func = command_strtoul(argv[1], NULL, 10); + AICWFDBG(LOGINFO, "fss %d\r\n", func); + rwnx_send_rftest_req(rwnx_hw, SET_FSS, sizeof(func), (u8_l *)&func, NULL); + } else { + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_set_usb_off (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + rwnx_send_rftest_req(rwnx_hw, SET_USB_OFF, 0, NULL, NULL); + return 0; +} + +static int aic_priv_cmd_set_pll_test (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + u8_l func = 0, tx_pwr = 0xc; + s8_l freq = 0; + + if (argc > 1) { + func = command_strtoul(argv[1], NULL, 16); + } + if (argc > 3) { + freq = (s8_l)command_strtoul(argv[2], NULL, 10); + tx_pwr = command_strtoul(argv[3], NULL, 16); + } + if (func <= 1) { + u8_l buf[3] = {func, (u8_l)freq, tx_pwr}; + AICWFDBG(LOGINFO, "set pll_test %d: freq=%d, tx_pwr=0x%x\n", func, freq, tx_pwr); + rwnx_send_rftest_req(rwnx_hw, SET_PLL_TEST, sizeof(buf), buf, &cfm); + } else { + AICWFDBG(LOGERROR, "wrong func: %x\n", func); + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_get_txpwr(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + s8_l power=0; + power = get_txpwr_max(power); + memcpy(command, &power, 1); + return 1; +} + +static int aic_priv_cmd_set_txpwr_loss(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + s8_l func; + if (argc > 1) { + func = (s8_l)command_strtoul(argv[1], NULL, 10); + printk("set txpwr loss: %d\n", func); + if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ + set_txpwr_loss_ofst(func); + rwnx_send_txpwr_lvl_v3_req(g_rwnx_plat->sdiodev->rwnx_hw); + }else{ + AICWFDBG(LOGINFO,"error:don't support ,now only support D40 D80"); + } + } else { + printk("wrong args\n"); + return -EINVAL; + } + return 0; +} + +static int aic_priv_cmd_help (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command) +{ + print_help(argc > 0 ? argv[0] : NULL); + return 0; +} + +struct aic_priv_cmd { + const char *cmd; + int (*handler)(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command); + const char *usage; +}; + +static const struct aic_priv_cmd aic_priv_commands[] = { + { "set_tx", aic_priv_cmd_set_tx, + " " }, + { "set_txstop", aic_priv_cmd_set_txstop, + "= stop tx " }, + { "set_rx", aic_priv_cmd_set_rx, + " " }, + { "get_rx_result", aic_priv_cmd_get_rx_result, + "= display rx fcsok/total pkt num" }, + { "set_rxstop", aic_priv_cmd_set_rxstop, + "= stop rx " }, + { "set_txtone", aic_priv_cmd_set_tx_tone, + " val = 0/off" }, + { "set_rx_meter", aic_priv_cmd_set_rx_meter, + "= set rx meter " }, + { "set_power", aic_priv_cmd_set_set_power, + " " }, + { "set_xtal_cap", aic_priv_cmd_set_xtal_cap, + " [0 ~ 31]" }, + { "set_xtal_cap_fine", aic_priv_cmd_set_xtal_cap_fine, + " [0 ~ 63]" }, + { "get_efuse_block", aic_priv_cmd_get_efuse_block, + "" }, + { "set_freq_cal", aic_priv_cmd_set_freq_cal, + "" }, + { "set_freq_cal_fine", aic_priv_cmd_set_freq_cal_fine, + "" }, + { "get_freq_cal", aic_priv_cmd_get_freq_cal, + "= display cap & cap fine" }, + { "set_mac_addr", aic_priv_cmd_set_mac_addr, + "= write WiFi MAC into efuse or flash is limited to a maximum of two times" }, + { "get_mac_addr", aic_priv_cmd_get_mac_addr, + "= display WiFi MAC stored in efuse or flash" }, + { "set_bt_mac_addr", aic_priv_cmd_set_bt_mac_addr, + "= write BT MAC into efuse or flash is limited to a maximum of two times" }, + { "get_bt_mac_addr", aic_priv_cmd_get_bt_mac_addr, + "= display BT MAC stored in efuse or flash" }, + { "set_vendor_info", aic_priv_cmd_set_vendor_info, + "= write vendor info into efuse or flash is allowed only once" }, + { "get_vendor_info", aic_priv_cmd_get_vendor_info, + "= display vendor info stored in efuse or flash" }, + { "rdwr_pwrmm", aic_priv_cmd_rdwr_pwrmm, + " = 0/rdwr_pwrlvl, 1/set_power = read/write txpwr manul mode" }, + { "rdwr_pwridx", aic_priv_cmd_rdwr_pwridx, + " " }, + { "rdwr_pwrlvl", aic_priv_cmd_rdwr_pwrlvl, + " " }, + { "rdwr_pwrofst", aic_priv_cmd_rdwr_pwrofst, + " " }, + { "rdwr_pwrofstfine", aic_priv_cmd_rdwr_pwrofstfine, + " " }, + { "rdwr_drvibit", aic_priv_cmd_rdwr_drvibit, + " read/write 8800D pa drvibit" }, + { "set_cal_xtal", aic_priv_cmd_set_cal_xtal, + "= set cal xtal" }, + { "get_cal_xtal_res", aic_priv_cmd_get_cal_xtal_res, + "= get cal xtal result cap & cap_fine" }, + { "set_cob_cal", aic_priv_cmd_set_cob_cal, + " = dut cob test" }, + { "get_cob_cal_res", aic_priv_cmd_get_cob_cal_res, + "= get cob cal result" }, + { "do_cob_test", aic_priv_cmd_do_cob_test, + " = 0/xtal, 1/dis_xtal, 2/only_xtal" }, + { "rdwr_efuse_pwrofst", aic_priv_cmd_rdwr_efuse_pwrofst, + " limited to a maximum of two times" }, + { "rdwr_efuse_pwrofstfine", aic_priv_cmd_rdwr_efuse_pwrofstfine, + " limited to a maximum of two times" }, + { "rdwr_efuse_drvibit", aic_priv_cmd_rdwr_efuse_drvibit, + " = read/write 8800D efuse pa drvibitis allowed only once" }, + { "rdwr_efuse_usrdata", aic_priv_cmd_rdwr_efuse_usrdata, + " = read/write efuse usrdata" }, + { "rdwr_efuse_sdiocfg", aic_priv_cmd_rdwr_efuse_sdiocfg, + " = read/write sdiocfg_bit into efuse" }, + { "rdwr_efuse_usbvidpid", aic_priv_cmd_rdwr_efuse_usbvidpid, + " = read/write usb vid/pid into efuse" }, + { "rdwr_efuse_he_off", aic_priv_cmd_rdwr_efuse_he_off, + " = read/write he_off into efuse" }, + { "set_papr", aic_priv_cmd_set_papr, + " = configure papr filter to optimize sideband suppression" }, + { "set_notch", aic_priv_cmd_set_notch, + " = configure filter to optimize sideband suppression" }, + { "set_srrc", aic_priv_cmd_set_srrc, + " = disable/enable sideband suppression for SRRC" }, + { "set_fss", aic_priv_cmd_set_fss, + " = disable/enable treatment of spurious emissions and burrs" }, + { "set_usb_off", aic_priv_cmd_set_usb_off, + "= off usb configure before usb disconnect" }, + { "set_pll_test", aic_priv_cmd_set_pll_test, + " = use pll test to measure saturation power" }, + { "get_txpwr", aic_priv_cmd_get_txpwr, + "= get userconfig max txpwr" }, + { "set_txpwr_loss",aic_priv_cmd_set_txpwr_loss, + " = txpwr will change ,val can be negative" }, + +//Reserve for new aic_priv_cmd. + { "help", aic_priv_cmd_help, + "= show usage help" }, + { NULL, NULL, NULL } + +}; + + +/* + * Prints command usage, lines are padded with the specified string. + */ +static void print_help(const char *cmd) +{ + int n; + printk("commands:\n"); + for (n = 0; aic_priv_commands[n].cmd; n++) { + if (cmd != NULL) + printk("%s %s\n", aic_priv_commands[n].cmd, aic_priv_commands[n].usage); + } +} + +int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) +{ + const struct aic_priv_cmd *cmd, *match = NULL; + int count; + int bytes_written = 0; + char *argv[CMD_MAXARGS + 1]; + int argc; + struct rwnx_vif *vif = container_of(net->ieee80211_ptr, struct rwnx_vif, wdev); + struct rwnx_hw *p_rwnx_hw = vif->rwnx_hw; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + argc = parse_line(command, argv); + if (argc == 0) { + return -1; + } + + count = 0; + cmd = aic_priv_commands; + while (cmd->cmd) { + if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) + { + match = cmd; + if (strcasecmp(cmd->cmd, argv[0]) == 0) { + /* we have an exact match */ + count = 1; + break; + } + count++; + } + cmd++; + } + + if (count > 1) { + AICWFDBG(LOGINFO, "Ambiguous command '%s'; possible commands:", argv[0]); + cmd = aic_priv_commands; + while (cmd->cmd) { + if (strncasecmp(cmd->cmd, argv[0], + strlen(argv[0])) == 0) { + AICWFDBG(LOGINFO, " %s", cmd->cmd); + } + cmd++; + } + AICWFDBG(LOGINFO, "\n"); + } else if (count == 0) { + AICWFDBG(LOGERROR, "Unknown command '%s'\n", argv[0]); + } else { + AICWFDBG(LOGINFO, "match %s", match->cmd); + bytes_written = match->handler(p_rwnx_hw, argc, &argv[0], command); + } + + if (bytes_written < 0) + AICWFDBG(LOGERROR, "wrong param\n"); + + return bytes_written; +} + +#define RWNX_COUNTRY_CODE_LEN 2 +#define CMD_SET_COUNTRY "COUNTRY" +#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" + + +struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); +struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, int index); +extern int reg_regdb_size; + +#ifdef CONFIG_SET_VENDOR_EXTENSION_IE +extern u8_l vendor_extension_data[256]; +extern int vendor_extension_len; + +void set_vendor_extension_ie(char *command){ + + char databyte[3]={0x00, 0x00, 0x00}; + int skip = strlen(CMD_SET_VENDOR_EX_IE) + 1; + int command_index = skip; + int data_index = 0; + + memset(vendor_extension_data, 0, 256); + vendor_extension_len = 0; + memcpy(databyte, command + command_index, 2); + vendor_extension_len = command_strtoul(databyte, NULL, 16); + printk("%s len:%d \r\n", __func__, vendor_extension_len); + + //parser command and save data in vendor_extension_data + for(data_index = 0;data_index < vendor_extension_len; data_index++){ + command_index = command_index + 3; + memcpy(databyte, command + command_index, 2); + vendor_extension_data[data_index] = command_strtoul(databyte, NULL, 16); + } + +} +#endif//CONFIG_SET_VENDOR_EXTENSION_IE + + +int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) +{ +#define PRIVATE_COMMAND_MAX_LEN 8192 +#define PRIVATE_COMMAND_DEF_LEN 4096 + + struct rwnx_vif *vif = netdev_priv(net); + int ret = 0; + char *command = NULL; + int bytes_written = 0; + android_wifi_priv_cmd priv_cmd; + int buf_size = 0; + int skip = 0; + char *country = NULL; + int setsusp_mode; + struct ieee80211_regdomain *regdomain; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + ///todo: add our lock + //net_os_wake_lock(net); + + +/* if (!capable(CAP_NET_ADMIN)) { + ret = -EPERM; + goto exit; + }*/ + if (!ifr->ifr_data) { + ret = -EINVAL; + goto exit; + } + +#ifdef CONFIG_COMPAT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) + if (in_compat_syscall()) +#else + if (is_compat_task()) +#endif + { + compat_android_wifi_priv_cmd compat_priv_cmd; + if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { + ret = -EFAULT; + goto exit; + } + priv_cmd.buf = compat_ptr(compat_priv_cmd.buf); + priv_cmd.used_len = compat_priv_cmd.used_len; + priv_cmd.total_len = compat_priv_cmd.total_len; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { + ret = -EFAULT; + goto exit; + } + } + if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { + printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); + ret = -EINVAL; + goto exit; + } + + buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); + command = kmalloc((buf_size + 1), GFP_KERNEL); + + if (!command) { + printk("%s: failed to allocate memory\n", __FUNCTION__); + ret = -ENOMEM; + goto exit; + } + if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { + ret = -EFAULT; + goto exit; + } + command[priv_cmd.total_len] = '\0'; + + /* outputs */ + AICWFDBG(LOGINFO, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); + AICWFDBG(LOGINFO, "cmd = %d\n", cmd); + AICWFDBG(LOGINFO, "buf_size=%d\n", buf_size); + +#if 1//Handle Android command + if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY))) { + skip = strlen(CMD_SET_COUNTRY) + 1; + country = command + skip; + if (!country || strlen(country) < RWNX_COUNTRY_CODE_LEN) { + printk("%s: invalid country code\n", __func__); + ret = -EINVAL; + goto exit; + } +#if 0 + for(index = 0; index < reg_regdb_size; index++){ + regdomain = getRegdomainFromRwnxDBIndex(vif->rwnx_hw->wiphy, index); + if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ + printk("regulatory_set_wiphy_regd fail \r\n"); + }else{ + printk("regulatory_set_wiphy_regd ok \r\n"); + } + } +#endif + AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, toupper(country[0]), toupper(country[1])); + regdomain = getRegdomainFromRwnxDB(vif->rwnx_hw->wiphy, country); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) + if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ + printk("regulatory_set_wiphy_regd fail \r\n"); + } +#else + wiphy_apply_custom_regulatory(vif->rwnx_hw->wiphy, regdomain); +#endif + } +#ifdef CONFIG_SET_VENDOR_EXTENSION_IE + else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){ + set_vendor_extension_ie(command); + } +#endif//CONFIG_SET_VENDOR_EXTENSION_IE + else if(!strncasecmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE))){ + ret = 0; + goto exit; + } + else if(!strncasecmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE))){ + skip = strlen(CMD_SET_COUNTRY) + 1; + setsusp_mode = command_strtoul(command + skip, NULL, 10); +#ifdef CONFIG_GPIO_WAKEUP + if (setsusp_mode == 1) { +#if defined(CONFIG_SDIO_PWRCTRL) + aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); +#endif//CONFIG_SDIO_PWRCTRL + ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); + if (ret < 0) { + sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); + } + } + AICWFDBG(LOGINFO, "set suspend mode %d\n", setsusp_mode); +#endif//CONFIG_GPIO_WAKEUP + goto exit; + } +#endif//Handle Android command + + bytes_written = handle_private_cmd(net, command, priv_cmd.total_len); + if (bytes_written >= 0) { + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { + command[0] = '\0'; + } + if (bytes_written >= priv_cmd.total_len) { + printk("%s: err. bytes_written:%d >= buf_size:%d \n", + __FUNCTION__, bytes_written, buf_size); + goto exit; + } + bytes_written++; + priv_cmd.used_len = bytes_written; + if (copy_to_user(priv_cmd.buf, command, bytes_written)) { + printk("%s: failed to copy data to user buffer\n", __FUNCTION__); + ret = -EFAULT; + } + } else { + /* Propagate the error */ + ret = bytes_written; + } + +exit: + ///todo: add our unlock + //net_os_wake_unlock(net); + kfree(command); + return ret; +} + +#ifdef CONFIG_MCU_MESSAGE +#define CMD_GET_VERSION_STR "GET_VERSION" +#define CMD_GET_SSID_STR "GET_SSID" +#define CMD_SET_SSID_STR "SET_SSID" +#define CMD_GET_PASS_STR "GET_PASS" +#define CMD_SET_PASS_STR "SET_PASS" +#define CMD_GET_VAR_STR "GET_VAR" +#define CMD_SET_VAR_STR "SET_VAR" + +enum custmsg_cmd_tag +{ + CUST_CMD_GET_VERSION = 0, + CUST_CMD_GET_SSID, + CUST_CMD_SET_SSID, + CUST_CMD_GET_PASS, + CUST_CMD_SET_PASS, + CUST_CMD_GET_VAR, + CUST_CMD_SET_VAR, + CUST_CMD_MAX +}; + +int handle_custom_msg(char *command, u32 cmd_len) +{ + int bytes_read = 0, max_bytes_to_read = 0; + struct rwnx_hw *p_rwnx_hw = NULL; + u32 cmd, len = 0, flags = 0; + char *buf = NULL; + struct dbg_custom_msg_cfm *cust_msg_cfm; + printk("cmd,%s,%ld\n",command,strlen(command)); + if (strncasecmp(command, CMD_GET_VERSION_STR, strlen(CMD_GET_VERSION_STR)) == 0) { + cmd = CUST_CMD_GET_VERSION; + max_bytes_to_read = 32; // max str len for version + } else if (strncasecmp(command, CMD_GET_SSID_STR, strlen(CMD_GET_SSID_STR)) == 0) { + cmd = CUST_CMD_GET_SSID; + max_bytes_to_read = 48; // max str len for ssid + } else if (strncasecmp(command, CMD_SET_SSID_STR, strlen(CMD_SET_SSID_STR)) == 0) { + cmd = CUST_CMD_SET_SSID; + len = cmd_len - (strlen(CMD_SET_SSID_STR) + 1); + buf = command + (strlen(CMD_SET_SSID_STR) + 1); + max_bytes_to_read = 0; + } else if (strncasecmp(command, CMD_GET_PASS_STR, strlen(CMD_GET_PASS_STR)) == 0) { + cmd = CUST_CMD_GET_PASS; + max_bytes_to_read = 64; // max str len for PASS + } else if (strncasecmp(command, CMD_SET_PASS_STR, strlen(CMD_SET_PASS_STR)) == 0) { + cmd = CUST_CMD_SET_PASS; + len = cmd_len - (strlen(CMD_SET_PASS_STR) + 1); + buf = command + (strlen(CMD_SET_PASS_STR) + 1); + max_bytes_to_read = 0; + } else if (strncasecmp(command, CMD_GET_VAR_STR, strlen(CMD_GET_VAR_STR)) == 0) { + cmd = CUST_CMD_GET_VAR; + max_bytes_to_read = 64; // max str len for VAR + } else if (strncasecmp(command, CMD_SET_VAR_STR, strlen(CMD_SET_VAR_STR)) == 0) { + cmd = CUST_CMD_SET_VAR; + len = cmd_len - (strlen(CMD_SET_VAR_STR) + 1); + buf = command + (strlen(CMD_SET_VAR_STR) + 1); + max_bytes_to_read = 0; + } else { + printk("invalid cmd: %s\r\n", command); + return -1; + } + if (len < 0) { + printk("invalid len: %d\r\n", len); + return -3; + } + #ifdef AICWF_SDIO_SUPPORT + p_rwnx_hw = g_rwnx_plat->sdiodev->rwnx_hw; + #endif + #ifdef AICWF_USB_SUPPORT + p_rwnx_hw = g_rwnx_plat->usbdev->rwnx_hw; + #endif + cust_msg_cfm = (struct dbg_custom_msg_cfm *)kmalloc((offsetof(struct dbg_custom_msg_cfm, buf) + max_bytes_to_read), GFP_KERNEL); + if (cust_msg_cfm == NULL) { + printk("msg cfm alloc fail\r\n"); + return -2; + } + rwnx_send_dbg_custom_msg_req(p_rwnx_hw, cmd, buf, len, flags, cust_msg_cfm); + bytes_read = cust_msg_cfm->len; + printk("Custom msg cfm: cmd=%d, len=%d, status=%x\n", cust_msg_cfm->cmd, bytes_read, cust_msg_cfm->status); + if (bytes_read) { + memcpy(command, cust_msg_cfm->buf, bytes_read); + command[bytes_read] = '\0'; + } else { + command[0] = '\0'; + } + if (cust_msg_cfm->status) { + printk("cfm status: %x", cust_msg_cfm->status); + } + return bytes_read; +} + +int devipc_cust_msg(struct net_device *net, struct ifreq *ifr, int cmd) +{ +#ifdef PRIVATE_COMMAND_MAX_LEN +#undef PRIVATE_COMMAND_MAX_LEN +#undef PRIVATE_COMMAND_DEF_LEN +#define PRIVATE_COMMAND_MAX_LEN 8192 +#define PRIVATE_COMMAND_DEF_LEN 4096 +#endif + int ret = 0; + char *command = NULL; + int bytes_written = 0; + android_wifi_priv_cmd priv_cmd; + int buf_size = 0; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + ///todo: add our lock + //net_os_wake_lock(net); + + +/* if (!capable(CAP_NET_ADMIN)) { + ret = -EPERM; + goto exit; + }*/ + if (!ifr->ifr_data) { + ret = -EINVAL; + goto exit; + } + +#ifdef CONFIG_COMPAT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) + if (in_compat_syscall()) +#else + if (is_compat_task()) +#endif + { + compat_android_wifi_priv_cmd compat_priv_cmd; + if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { + ret = -EFAULT; + goto exit; + } + priv_cmd.buf = compat_ptr(compat_priv_cmd.buf); + priv_cmd.used_len = compat_priv_cmd.used_len; + priv_cmd.total_len = compat_priv_cmd.total_len; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { + ret = -EFAULT; + goto exit; + } + } + if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { + printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); + ret = -EINVAL; + goto exit; + } + + buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); + command = kmalloc((buf_size + 1), GFP_KERNEL); + + if (!command) + { + printk("%s: failed to allocate memory\n", __FUNCTION__); + ret = -ENOMEM; + goto exit; + } + if (copy_from_user(command, priv_cmd.buf, priv_cmd.used_len)) { + ret = -EFAULT; + goto exit; + } + command[priv_cmd.used_len] = '\0'; + + /* outputs */ + printk("%s: Devipc custom msg \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); + printk("cmd = %x\n", cmd); + printk("buf_size=%d\n", buf_size); + + + bytes_written = handle_custom_msg(command, priv_cmd.used_len); + if (bytes_written >= 0) { + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { + command[0] = '\0'; + } + if (bytes_written >= priv_cmd.total_len) { + printk("%s: err. bytes_written:%d >= buf_size:%d \n", + __FUNCTION__, bytes_written, buf_size); + goto exit; + } + bytes_written++; + priv_cmd.used_len = bytes_written; + if (copy_to_user(priv_cmd.buf, command, bytes_written)) { + printk("%s: failed to copy data to user buffer\n", __FUNCTION__); + ret = -EFAULT; + } + } + else { + /* Propagate the error */ + ret = bytes_written; + } + +exit: + ///todo: add our unlock + //net_os_wake_unlock(net); + kfree(command); + Sreturn ret; +} +#endif + diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_priv_cmd.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_priv_cmd.h new file mode 100755 index 000000000..265658ed1 --- /dev/null +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_priv_cmd.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * + * @file private_cmd.h + * + * Copyright (C) Aicsemi 2018-2024 + * + ****************************************************************************** + */ + +#ifndef _AIC_PRIV_CMD_H_ +#define _AIC_PRIV_CMD_H_ + +#include "rwnx_defs.h" + +typedef struct _android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +} android_wifi_priv_cmd; + +#ifdef CONFIG_COMPAT +typedef struct _compat_android_wifi_priv_cmd { + compat_caddr_t buf; + int used_len; + int total_len; +} compat_android_wifi_priv_cmd; +#endif /* CONFIG_COMPAT */ + +int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); + +#endif /* _AIC_PRIV_CMD_H_ */ + diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_vendor.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_vendor.c index 0cc6d5a39..7dead4b31 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_vendor.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aic_vendor.c @@ -27,6 +27,15 @@ static struct wifi_ring_buffer_status ring_buffer[] = { static struct wlan_driver_wake_reason_cnt_t wake_reason_cnt = { .total_cmd_event_wake = 10, }; + +enum apf_attributes { + APF_ATTRIBUTE_VERSION, + APF_ATTRIBUTE_MAX_LEN, + APF_ATTRIBUTE_PROGRAM, + APF_ATTRIBUTE_PROGRAM_LEN, + APF_ATTRIBUTE_MAX +}; + #endif int aic_dev_start_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, @@ -578,7 +587,69 @@ out_put_fail: return -EMSGSIZE; } -static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, +static int aicwf_vendor_logger_get_tx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int len) +{ +#if 0 + int ret = 0, rem, type; + const struct nlattr *iter; + int fate_num; + int fate_data; + + AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); + nla_for_each_attr(iter, data, len, rem) { + type = nla_type(iter); + switch (type) { + case LOGGER_ATTRIBUTE_PKT_FATE_NUM: + fate_num = nla_get_u32(iter); + break; + case LOGGER_ATTRIBUTE_PKT_FATE_DATA: + fate_data = nla_get_u64(iter); + break; + default: + AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); + return -EINVAL; + } + } +#endif + /* TODO + * Add handle in the future + */ + return 0; +} + +static int aicwf_vendor_logger_get_rx_pkt_fates(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int len) +{ +#if 0 + int ret = 0, rem, type; + const struct nlattr *iter; + int fate_num; + int fate_data; + + AICWFDBG(LOGDEBUG, "%s Enter\r\n", __func__); + nla_for_each_attr(iter, data, len, rem) { + type = nla_type(iter); + switch (type) { + case LOGGER_ATTRIBUTE_PKT_FATE_NUM: + fate_num = nla_get_u32(iter); + break; + case LOGGER_ATTRIBUTE_PKT_FATE_DATA: + fate_data = nla_get_u64(iter); + break; + default: + AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type); + return -EINVAL; + } + } +#endif + /* TODO + * Add handle in the future + */ + return 0; +} + +static int aicwf_vendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { /* TODO @@ -587,6 +658,44 @@ static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct return 0; } +static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int len) +{ + int ver, max_len; + int ret = 0; + struct sk_buff *skb = NULL; + + /* APF version */ + ver = 4; + /* APF memory size limit */ + max_len = 2048; + + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, max_len); + + ret = nla_put_u32(skb, APF_ATTRIBUTE_VERSION, ver); + if (ret < 0) { + AICWFDBG(LOGERROR, "Failed to put APF_ATTRIBUTE_VERSION, ret:%d\n", ret); + goto fail; + } + ret = nla_put_u32(skb, APF_ATTRIBUTE_MAX_LEN, max_len); + if (ret < 0) { + AICWFDBG(LOGERROR, "Failed to put APF_ATTRIBUTE_MAX_LEN, ret:%d\n", ret); + goto fail; + } + + ret = cfg80211_vendor_cmd_reply(skb); + if (unlikely(ret)) { + AICWFDBG(LOGERROR, "vendor command reply failed, ret=%d\n", ret); + } + +fail: + /* TODO + * Add handle in the future + */ + return ret; +} + static int aicwf_vendor_sub_cmd_set_mac(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { @@ -855,6 +964,48 @@ const struct wiphy_vendor_command aicwf_vendor_cmd[] = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) .dumpit = aicwf_dump_interface, #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) + .policy = VENDOR_CMD_RAW_DATA, +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_START_PKT_FATE_MONITORING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = aicwf_vendor_logger_start_pkt_fate_monitoring, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) + .dumpit = aicwf_dump_interface, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) + .policy = VENDOR_CMD_RAW_DATA, +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_TX_PKT_FATES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = aicwf_vendor_logger_get_tx_pkt_fates, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) + .dumpit = aicwf_dump_interface, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) + .policy = VENDOR_CMD_RAW_DATA, +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_RX_PKT_FATES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = aicwf_vendor_logger_get_rx_pkt_fates, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) + .dumpit = aicwf_dump_interface, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) .policy = VENDOR_CMD_RAW_DATA, #endif @@ -889,6 +1040,7 @@ const struct wiphy_vendor_command aicwf_vendor_cmd[] = { .maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX, #endif }, + }; #endif diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800d80.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800d80.c index 72eeb93ce..7f50fe6bf 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800d80.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800d80.c @@ -20,15 +20,17 @@ int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_ return -1; } + if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) { + return -1; + } + if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) { return -1; } - if (testmode == 0) { if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) { - return -1; - } - } + return -1; + } return 0 ; } diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800dc.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800dc.c index f817fc042..c3de44526 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800dc.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_compat_8800dc.c @@ -16,6 +16,7 @@ void rwnx_plat_userconfig_parsing2(char *buffer, int size); void rwnx_release_firmware_common(u32** buffer); +#if !defined(CONFIG_EXT_FEM_8800DCDW) u32 wifi_txgain_table_24g_8800dcdw[32] = { 0xA4B22189, //index 0 @@ -160,6 +161,80 @@ u32 wifi_txgain_table_24g_1_8800dcdw_h[32] = 0x00001825, }; +#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ +// ofdm +uint32_t wifi_txgain_table_24g_8800dcdw_femkct[32] = { + 0x919221C2, //index 0 + 0x00007825, + 0x899221C3, //index 1 + 0x00007825, + 0x8B9221C3, //index 2 + 0x00007825, + 0x929221C3, //index 3 + 0x00007825, + 0x949221C4, //index 4 + 0x00007825, + 0x969221C4, //index 5 + 0x00007825, + 0x949221C6, //index 6 + 0x00007825, + 0x949221C8, //index 7 + 0x00007825, + 0x9C9221C8, //index 8 + 0x00007825, + 0x9C9221CA, //index 9 + 0x00007825, + 0x9C9221CB, //index 10 + 0x00007825, + 0x939221D5, //index 11 + 0x00007825, + 0x9B9221D7, //index 12 + 0x00007825, + 0xA49221D7, //index 13 + 0x00007825, + 0xA79221D7, //index 14 + 0x00007825, + 0xBD9221D7, //index 15 + 0x00007825, +}; + +// 11b +uint32_t wifi_txgain_table_24g_1_8800dcdw_femkct[32] = { + 0x836E20C2, //index 0 + 0x00003024, + 0x856E20C2, //index 1 + 0x00003024, + 0x826E20C3, //index 2 + 0x00003024, + 0x836E20C3, //index 3 + 0x00003024, + 0x856E20C3, //index 4 + 0x00003024, + 0x876E20C3, //index 5 + 0x00003024, + 0x8B6E20C3, //index 6 + 0x00003024, + 0x926E20C4, //index 7 + 0x00003024, + 0x9A6E20C4, //index 8 + 0x00003024, + 0x936E20C5, //index 9 + 0x00003024, + 0x936E20C7, //index 10 + 0x00003024, + 0xA16E20C8, //index 11 + 0x00003024, + 0xA16E20CA, //index 12 + 0x00003024, + 0xA26E20CB, //index 13 + 0x00003024, + 0xAA6E20CD, //index 14 + 0x00003024, + 0xAC7220CF, //index 15 + 0x00003024, +}; +#endif + u32 wifi_rxgain_table_24g_20m_8800dcdw[64] = { 0x82f282d1,//index 0 0x9591a324, @@ -423,6 +498,7 @@ int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_c if (testmode == 0) { + #if !defined(CONFIG_EXT_FEM_8800DCDW) if (IS_CHIP_ID_H()) { if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_h, 128))) return -1; @@ -436,6 +512,18 @@ int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_c if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw, 128))) return -1; } + #else /* #ifdef CONFIG_EXT_FEM_8800DCDW */ + { + ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_femkct, 128); + if (ret) { + return -1; + } + ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_femkct, 128); + if (ret) { + return -1; + } + } + #endif if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 0, (u8_l *)wifi_rxgain_table_24g_20m_8800dcdw, 256))) return -1; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_debug.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_debug.h index 25a576656..6fdb3ee9e 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_debug.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_debug.h @@ -20,6 +20,8 @@ void rwnx_data_dump(char* tag, void* data, unsigned long len); #define AICWF_LOG "AICWFDBG(" + +#ifdef DEBUG #define AICWFDBG(level, args, arg...) \ do { \ if (aicwf_dbg_level & level) { \ @@ -33,8 +35,12 @@ do { \ printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ } \ } while (0) +#else +#define AICWFDBG(level, args, arg...) +#define RWNX_DBG(fmt, ...) +#endif #if 0 #define RWNX_DBG(fmt, ...) \ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.c index 53c9710dd..422532ba2 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.c @@ -57,6 +57,13 @@ struct proc_dir_entry *wifi_suspend_node; int tx_aggr_counter = 32; module_param_named(tx_aggr_counter, tx_aggr_counter, int, 0644); +#ifdef CONFIG_TX_NETIF_FLOWCTRL +int tx_fc_low_water = AICWF_SDIO_TX_LOW_WATER; +module_param_named(tx_fc_low_water, tx_fc_low_water, int, 0644); + +int tx_fc_high_water = AICWF_SDIO_TX_HIGH_WATER; +module_param_named(tx_fc_high_water, tx_fc_high_water, int, 0644); +#endif int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) { @@ -76,6 +83,21 @@ int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) return ret; } +#ifdef CONFIG_TX_NETIF_FLOWCTRL +void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state) +{ + struct rwnx_vif *rwnx_vif; + list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { + if (! rwnx_vif->up) + continue; + if (state) + netif_tx_stop_all_queues(rwnx_vif->ndev);//netif_stop_queue(rwnx_vif->ndev); + else + netif_tx_wake_all_queues(rwnx_vif->ndev);//netif_wake_queue(rwnx_vif->ndev); + } +} +#endif + int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev) { int ret = -1; @@ -398,7 +420,9 @@ static int rwnx_register_hostwake_irq(struct device *dev) //ws_rx_sdio = wakeup_source_register(dev, "wifi_rx_sleep"); //ws_sdio_pwrctrl = wakeup_source_register(dev, "sdio_pwrctrl_sleep"); #else +#ifdef ANDROID_PLATFORM wake_lock_init(&irq_wakelock, WAKE_LOCK_SUSPEND, "wifisleep"); +#endif #endif ret = device_init_wakeup(dev, true); if (ret < 0) { @@ -442,8 +466,10 @@ fail1: //wakeup_source_unregister(ws_rx_sdio); //wakeup_source_unregister(ws_sdio_pwrctrl); #else +#ifdef ANDROID_PLATFORM wake_lock_destroy(&irq_wakelock); #endif +#endif #endif//CONFIG_GPIO_WAKEUP return ret; } @@ -681,6 +707,7 @@ void aicwf_sdio_remove_(struct sdio_func *func){ aicwf_sdio_remove(func); } +#ifdef SDIO_REMOVEABLE static int aicwf_sdio_suspend(struct device *dev) { int ret = 0; @@ -764,11 +791,6 @@ static int aicwf_sdio_resume(struct device *dev) aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); #endif - #ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX - rwnx_set_wifi_suspend('0'); - #endif//CONFIG_WIFI_SUSPEND_FOR_LINUX - - // aicwf_sdio_hal_irqhandler(sdiodev->func); #if defined(CONFIG_PLATFORM_ROCKCHIP) || defined(CONFIG_PLATFORM_ROCKCHIP2) @@ -786,10 +808,15 @@ static int aicwf_sdio_resume(struct device *dev) #endif atomic_set(&sdiodev->is_bus_suspend, 0); // smp_mb(); + #ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX + rwnx_set_wifi_suspend('0'); + #endif//CONFIG_WIFI_SUSPEND_FOR_LINUX + sdio_dbg("%s exit\n", __func__); return 0; } +#endif static const struct sdio_device_id aicwf_sdmmc_ids[] = { {SDIO_DEVICE(SDIO_VENDOR_ID_AIC8801, SDIO_DEVICE_ID_AIC8801)}, @@ -1259,6 +1286,9 @@ static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) { int err = 0; +#ifdef CONFIG_TX_NETIF_FLOWCTRL + unsigned long flags; +#endif if (sdiodev->bus_if->state == BUS_DOWN_ST) { sdio_err("Bus is down\n"); @@ -1323,6 +1353,19 @@ static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) } } +#ifdef CONFIG_TX_NETIF_FLOWCTRL + spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); + if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { + //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", + // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); + if (sdiodev->flowctrl) { + sdiodev->flowctrl = 0; + aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); + } + } + spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); +#endif + up(&sdiodev->tx_priv->txctl_sema); } @@ -1334,6 +1377,9 @@ static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) int headroom = 0; struct aicwf_bus *bus_if = dev_get_drvdata(dev); struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; +#ifdef CONFIG_TX_NETIF_FLOWCTRL + unsigned long flags; +#endif if (bus_if->state == BUS_DOWN_ST) { sdio_err("bus_if stopped\n"); @@ -1355,6 +1401,7 @@ static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) consume_skb(pkt); spin_unlock_bh(&sdiodev->tx_priv->txqlock); return -ENOSR; + goto flowctrl; } else { ret = 0; } @@ -1363,6 +1410,20 @@ static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) spin_unlock_bh(&sdiodev->tx_priv->txqlock); complete(&bus_if->bustx_trgg); + flowctrl: +#ifdef CONFIG_TX_NETIF_FLOWCTRL + spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); + if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water) { + //printk("sdiodev->tx_priv->tx_pktcnt >= tx_fc_high_water:%d %d\r\n", + // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_high_water); + if (!sdiodev->flowctrl) { + sdiodev->flowctrl = 1; + aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, true); + } + } + spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); +#endif + return ret; } @@ -1407,6 +1468,9 @@ int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow) struct sk_buff *pkt; struct aic_sdio_dev *sdiodev = tx_priv->sdiodev; u32 aggr_len = 0; +#ifdef CONFIG_TX_NETIF_FLOWCTRL + unsigned long flags; +#endif aggr_len = (tx_priv->tail - tx_priv->head); if (((atomic_read(&tx_priv->aggr_count) == 0) && (aggr_len != 0)) @@ -1432,6 +1496,19 @@ int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow) atomic_dec(&sdiodev->tx_priv->tx_pktcnt); spin_unlock_bh(&sdiodev->tx_priv->txqlock); +#ifdef CONFIG_TX_NETIF_FLOWCTRL + spin_lock_irqsave(&sdiodev->tx_flow_lock, flags); + if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) < tx_fc_low_water) { + //printk("sdiodev->tx_priv->tx_pktcnt < tx_fc_low_water:%d %d\r\n", + // atomic_read(&sdiodev->tx_priv->tx_pktcnt), tx_fc_low_water); + if (sdiodev->flowctrl) { + sdiodev->flowctrl = 0; + aicwf_sdio_tx_netif_flowctrl(sdiodev->rwnx_hw, false); + } + } + spin_unlock_irqrestore(&sdiodev->tx_flow_lock, flags); +#endif + if (tx_priv == NULL || tx_priv->tail == NULL || pkt == NULL) txrx_err("null error\n"); if (aicwf_sdio_aggr(tx_priv, pkt)) { @@ -1575,7 +1652,7 @@ static int aicwf_sdio_bus_start(struct device *dev) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) #include "uapi/linux/sched/types.h" -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) #include "linux/sched/types.h" #else #include "linux/sched/rt.h" @@ -1947,15 +2024,16 @@ void aicwf_sdio_hal_irqhandler(struct sdio_func *func) return; } +#ifdef CONFIG_PREALLOC_RX_SKB + if (list_empty(&aic_rx_buff_list.rxbuff_list)) { + printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); + rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); + return; + } +#endif + if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || sdiodev->chipid == PRODUCT_ID_AIC8800DW) { - #ifdef CONFIG_PREALLOC_RX_SKB - if (list_empty(&aic_rx_buff_list.rxbuff_list)) { - printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); - rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_irqrx); - return; - } - #endif ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.block_cnt_reg, &intstatus); while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); @@ -2081,24 +2159,32 @@ static struct aicwf_bus_ops aicwf_sdio_bus_ops = { void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) { struct aicwf_bus *bus_if; -#ifdef CONFIG_OOB - int ret; -#endif + int ret; + AICWFDBG(LOGINFO, "%s Enter\n", __func__); bus_if = dev_get_drvdata(sdiodev->dev); bus_if->state = BUS_DOWN_ST; #ifdef CONFIG_OOB - if(sdiodev->oob_enable){ - sdio_claim_host(sdiodev->func); - //disable sdio interrupt - ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); - if (ret < 0) { - AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); - } - sdio_release_irq(sdiodev->func); - sdio_release_host(sdiodev->func); - } + if(sdiodev->oob_enable){ + sdio_claim_host(sdiodev->func); + //disable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); + if (ret < 0) { + AICWFDBG(LOGERROR, "reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); + } + sdio_release_irq(sdiodev->func); + sdio_release_host(sdiodev->func); + } +#else + sdio_claim_host(sdiodev->func); + //disable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev, sdiodev->sdio_reg.intr_config_reg, 0x0); + if (ret < 0) { + sdio_err("reg:%d write failed!\n", sdiodev->sdio_reg.intr_config_reg); + } + sdio_release_irq(sdiodev->func); + sdio_release_host(sdiodev->func); #endif if (sdiodev->dev) aicwf_bus_deinit(sdiodev->dev); @@ -2404,6 +2490,10 @@ void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) sdiodev->pwrctl_tsk = NULL; } #endif +#ifdef CONFIG_TX_NETIF_FLOWCTRL + sdiodev->flowctrl = 0; + spin_lock_init(&sdiodev->tx_flow_lock); +#endif ret = aicwf_bus_init(0, sdiodev->dev); if (ret < 0) { @@ -2457,11 +2547,13 @@ void rwnx_set_wifi_suspend(char onoff){ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 0); }else{ printk("%s suspend \r\n", __func__); - rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1); - aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); - ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); - if (ret < 0) { - sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); + ret = rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1); + if (!ret) { + aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); + ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); + if (ret < 0) { + sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); + } } } } diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.h index 19ec8472d..4ca6de280 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_sdio.h @@ -57,6 +57,10 @@ #define SDIO_ACTIVE_ST 1 #define DATA_FLOW_CTRL_THRESH 2 +#ifdef CONFIG_TX_NETIF_FLOWCTRL +#define AICWF_SDIO_TX_LOW_WATER 100 +#define AICWF_SDIO_TX_HIGH_WATER 500 +#endif typedef enum { SDIO_TYPE_DATA = 0X00, @@ -110,6 +114,10 @@ struct aic_sdio_dev { struct aicwf_rx_priv *rx_priv; struct aicwf_tx_priv *tx_priv; u32 state; +#ifdef CONFIG_TX_NETIF_FLOWCTRL + u8 flowctrl; + spinlock_t tx_flow_lock; +#endif #if defined(CONFIG_SDIO_PWRCTRL) //for sdio pwr ctrl @@ -139,6 +147,9 @@ void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); +#ifdef CONFIG_TX_NETIF_FLOWCTRL +void aicwf_sdio_tx_netif_flowctrl(struct rwnx_hw *rwnx_hw, bool state); +#endif int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev); #ifdef CONFIG_PREALLOC_RX_SKB diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.c index 6d766bc75..fa30efd81 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.c @@ -7,7 +7,7 @@ struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg) { //printk("%s \n",__func__); int len=sizeof(struct msg_buf) ; - msg = kzalloc(len , GFP_KERNEL); + msg = kzalloc(len , /*GFP_KERNEL*/GFP_ATOMIC); if(!msg) printk("%s: alloc failed \n", __func__); memset(msg,0,len); diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.h index ff7f11d91..d872e635c 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/aicwf_tcp_ack.h @@ -36,10 +36,10 @@ struct msg_buf { u8 mode; u16 len; unsigned long timeout;*/ - /* marlin 2 */ + /*unsigned int fifo_id; struct sprdwl_msg_list *msglist;*/ - /* marlin 3 */ + /*unsigned char buffer_type; struct sprdwl_xmit_msg_list *xmit_msg_list; unsigned char msg_type; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/lmac_msg.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/lmac_msg.h index 10b0fe5d2..92452942d 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/lmac_msg.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/lmac_msg.h @@ -394,6 +394,9 @@ enum mm_msg_tag { MM_SET_VENDOR_SWCONFIG_REQ, MM_SET_VENDOR_SWCONFIG_CFM, + MM_SET_TXPWR_LVL_ADJ_REQ, + MM_SET_TXPWR_LVL_ADJ_CFM, + /// MAX number of messages MM_MAX, }; @@ -1160,6 +1163,7 @@ struct mm_set_arpoffload_en_cfm { struct mm_set_agg_disable_req { u8_l disable; u8_l staidx; + u8_l disable_rx; }; struct mm_set_coex_req { @@ -1259,6 +1263,13 @@ typedef struct s8_l pwrlvl_11ax_5g[12]; } txpwr_lvl_conf_v3_t; +typedef struct +{ + u8_l enable; + s8_l pwrlvl_adj_tbl_2g4[3]; + s8_l pwrlvl_adj_tbl_5g[6]; +} txpwr_lvl_adj_conf_t; + typedef struct { u8_l loss_enable; @@ -1274,6 +1285,10 @@ struct mm_set_txpwr_lvl_req }; }; +struct mm_set_txpwr_lvl_adj_req +{ + txpwr_lvl_adj_conf_t txpwr_lvl_adj; +}; typedef struct { u8_l enable; @@ -1834,11 +1849,19 @@ struct me_traffic_ind_req { struct mm_apm_staloss_ind { - u8_l sta_idx; - u8_l vif_idx; - u8_l mac_addr[6]; + u8_l sta_idx; + u8_l vif_idx; + u8_l mac_addr[6]; }; +#ifdef CONFIG_SDIO_BT +struct mm_bt_recv_ind +{ + u32_l data_len; + u8_l bt_data[1024]; +}; +#endif + enum vendor_hwconfig_tag{ ACS_TXOP_REQ = 0, CHANNEL_ACCESS_REQ, @@ -1846,6 +1869,10 @@ enum vendor_hwconfig_tag{ CCA_THRESHOLD_REQ, BWMODE_REQ, CHIP_TEMP_GET_REQ, + AP_PS_LEVEL_SET_REQ, + CUSTOMIZED_FREQ_REQ, + WAKEUP_INFO_REQ, + KEEPALIVE_PKT_REQ, }; enum { @@ -1915,6 +1942,12 @@ struct mm_get_chip_temp_cfm s8_l degree; }; +struct mm_set_ap_ps_level_req +{ + u32_l hwconfig_id; + u8 ap_ps_level; +}; + struct mm_set_vendor_hwconfig_cfm { u32_l hwconfig_id; @@ -1923,6 +1956,31 @@ struct mm_set_vendor_hwconfig_cfm }; }; +struct mm_set_customized_freq_req +{ + u32_l hwconfig_id; + u16_l raw_freq[4]; + u16_l map_freq[4]; +}; + +struct mm_set_wakeup_info_req +{ + u32_l hwconfig_id; + u16_l offset; + u8_l length; + u8_l mask_and_patten[]; + +}; + +struct mm_set_keepalive_req +{ + u32_l hwconfig_id; + u16_l code; + u16_l length; + u32_l intv; + u8_l payload[]; +}; + struct mm_set_txop_req { u16_l txop_bk; @@ -1949,6 +2007,9 @@ enum vendor_swconfig_tag BCN_CFG_REQ = 0, TEMP_COMP_SET_REQ, TEMP_COMP_GET_REQ, + EXT_FLAGS_SET_REQ, + EXT_FLAGS_GET_REQ, + EXT_FLAGS_MASK_SET_REQ, }; struct mm_set_bcn_cfg_req @@ -1985,12 +2046,40 @@ struct mm_get_temp_comp_cfm s8_l degree; }; +struct mm_set_ext_flags_req +{ + u32_l user_flags; +}; + +struct mm_set_ext_flags_cfm +{ + u32_l user_flags; +}; + +struct mm_get_ext_flags_cfm +{ + u32_l user_flags; +}; + +struct mm_mask_set_ext_flags_req +{ + u32_l user_flags_mask; + u32_l user_flags_val; +}; + +struct mm_mask_set_ext_flags_cfm +{ + u32_l user_flags; +}; + struct mm_set_vendor_swconfig_req { u32_l swconfig_id; union { struct mm_set_bcn_cfg_req bcn_cfg_req; struct mm_set_temp_comp_req temp_comp_set_req; + struct mm_set_ext_flags_req ext_flags_set_req; + struct mm_mask_set_ext_flags_req ext_flags_mask_set_req; }; }; @@ -2001,9 +2090,25 @@ struct mm_set_vendor_swconfig_cfm struct mm_set_bcn_cfg_cfm bcn_cfg_cfm; struct mm_set_temp_comp_cfm temp_comp_set_cfm; struct mm_get_temp_comp_cfm temp_comp_get_cfm; + struct mm_set_ext_flags_cfm ext_flags_set_cfm; + struct mm_get_ext_flags_cfm ext_flags_get_cfm; + struct mm_mask_set_ext_flags_cfm ext_flags_mask_set_cfm; }; }; +#ifdef CONFIG_SDIO_BT +struct mm_bt_send_req +{ + u32_l data_len; + u8_l bt_data[1024]; +}; + +struct mm_bt_send_cfm +{ + u8_l status; +}; +#endif + /// Structure containing the parameters of the @ref ME_RC_STATS_REQ message. struct me_rc_stats_req { /// Index of the station for which the RC statistics are requested @@ -2697,22 +2802,36 @@ enum dbg_msg_tag { /// Memory mask write confirm DBG_MEM_MASK_WRITE_CFM, - DBG_RFTEST_CMD_REQ, - DBG_RFTEST_CMD_CFM, - DBG_BINDING_REQ, - DBG_BINDING_CFM, - DBG_BINDING_IND, + DBG_RFTEST_CMD_REQ, + DBG_RFTEST_CMD_CFM, + DBG_BINDING_REQ, + DBG_BINDING_CFM, + DBG_BINDING_IND, - DBG_CUSTOM_MSG_REQ, - DBG_CUSTOM_MSG_CFM, - DBG_CUSTOM_MSG_IND, + DBG_CUSTOM_MSG_REQ, + DBG_CUSTOM_MSG_CFM, + DBG_CUSTOM_MSG_IND, - DBG_GPIO_WRITE_REQ, - DBG_GPIO_WRITE_CFM, - DBG_GPIO_READ_REQ, - DBG_GPIO_READ_CFM, - DBG_GPIO_INIT_REQ, - DBG_GPIO_INIT_CFM, + DBG_GPIO_WRITE_REQ, + DBG_GPIO_WRITE_CFM, + DBG_GPIO_READ_REQ, + DBG_GPIO_READ_CFM, + DBG_GPIO_INIT_REQ, + DBG_GPIO_INIT_CFM, + + /// EF usrdata read request + DBG_EF_USRDATA_READ_REQ, + /// EF usrdata read confirm + DBG_EF_USRDATA_READ_CFM, + /// Memory block read request + DBG_MEM_BLOCK_READ_REQ, + /// Memory block read confirm + DBG_MEM_BLOCK_READ_CFM, + + DBG_PWM_INIT_REQ, + DBG_PWM_INIT_CFM, + DBG_PWM_DEINIT_REQ, + DBG_PWM_DEINIT_CFM, /// Max number of Debug messages DBG_MAX, @@ -2883,6 +3002,12 @@ enum tdls_msg_tag { TDLS_PEER_TRAFFIC_IND_REQ, /// TDLS peer traffic indication confirmation. TDLS_PEER_TRAFFIC_IND_CFM, + +#ifdef CONFIG_SDIO_BT + TDLS_SDIO_BT_SEND_REQ = LMAC_FIRST_MSG(TASK_TDLS)+16, + TDLS_SDIO_BT_SEND_CFM, + TDLS_SDIO_BT_RECV_IND, +#endif /// MAX number of messages TDLS_MAX }; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/regdb.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/regdb.c index 0f8777066..c984c03f2 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/regdb.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/regdb.c @@ -2891,6 +2891,7 @@ const struct ieee80211_regdomain *reg_regdb[] = { ®dom_YT, ®dom_ZA, ®dom_ZW, + NULL, }; int reg_regdb_size = ARRAY_SIZE(reg_regdb); diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_debugfs.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_debugfs.c index f4594f4bc..f7e2dd2f6 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_debugfs.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_debugfs.c @@ -1334,6 +1334,14 @@ static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file, printk("CHIP_TEMP_GET_REQ degree=%d\n", addr_out[0]); } break; + case 6://AP_PS_LEVEL_SET_REQ + if (ret != 2) { + printk("param error != 2\n"); + } else { + ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL); + printk("AP_PS_LEVEL_SET_REQ lvl=%d\n", addr[0]); + } + break; default: printk("param error\n"); break; @@ -1346,7 +1354,7 @@ static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file, return count; } -DEBUGFS_WRITE_FILE_OPS(vendor_hwconfig) +DEBUGFS_WRITE_FILE_OPS(vendor_hwconfig); static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file, const char __user *user_buf, @@ -1400,6 +1408,35 @@ static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file, } break; + case 3: // EXT_FLAGS_SET_REQ + if (ret != 2) { + printk("param error != 2\n"); + } else { + ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); + printk("EXT_FLAGS_SET_REQ set ext_flags=0x%x, get ext_flags=0x%x\n", + addr[0], addr_out[0]); + } + break; + + case 4: // EXT_FLAGS_GET_REQ + if (ret != 1) { + printk("param error != 1\n"); + } else { + ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); + printk("EXT_FLAGS_GET_REQ get ext_flags=0x%x\n", addr_out[0]); + } + break; + + case 5: // EXT_FLAGS_MASK_SET_REQ + if (ret != 3) { + printk("param error != 3\n"); + } else { + ret = rwnx_send_vendor_swconfig_req(priv, swconfig_id, addr, addr_out); + printk("EXT_FLAGS_MASK_SET_REQ set ext_flags mask=0x%x, val=0x%x, get ext_flags=0x%x\n", + addr[0], addr[1], addr_out[0]); + } + break; + default: printk("param error\n"); break; @@ -1413,8 +1450,107 @@ static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file, return count; } -DEBUGFS_WRITE_FILE_OPS(vendor_swconfig) +DEBUGFS_WRITE_FILE_OPS(vendor_swconfig); +static ssize_t rwnx_dbgfs_agg_disable_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct rwnx_hw *priv = file->private_data; + char buf[64]; + int agg_disable, agg_disable_rx, sta_idx; + size_t len = min_t(size_t, count, sizeof(buf) - 1); + int ret; + printk("%s\n", __func__); + + if (copy_from_user(buf, user_buf, len)) { + return -EFAULT; + } + + buf[len] = '\0'; + ret = sscanf(buf, "%d %d %d", &agg_disable, &agg_disable_rx, &sta_idx); + if ((ret > 3) || (ret < 2)) { + printk("param error: cnt=%d\n", ret); + } else { + if (ret < 3) { + sta_idx = RWNX_INVALID_STA; + } + printk("disable_agg: T=%d, R=%d, staidx=%d\n", agg_disable, agg_disable_rx, sta_idx); + ret = rwnx_send_disable_agg_req(priv, (u8_l)agg_disable, (u8_l)agg_disable_rx, (u8_l)sta_idx); + if (ret) { + printk("rwnx_send_disable_agg_req fail: %d\n", ret); + } + } + + return count; +} + +DEBUGFS_WRITE_FILE_OPS(agg_disable); + +static ssize_t rwnx_dbgfs_set_roc_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct rwnx_hw *priv = file->private_data; + struct rwnx_vif *vif = NULL; + char buf[64]; + int roc_start, chan_freq, duration; + size_t len = min_t(size_t, count, sizeof(buf) - 1); + int ret; + int if_type = NL80211_IFTYPE_STATION; + printk("%s\n", __func__); + + if (copy_from_user(buf, user_buf, len)) { + return -EFAULT; + } + + buf[len] = '\0'; + ret = sscanf(buf, "%d %d %d", &roc_start, &chan_freq, &duration); + + list_for_each_entry(vif, &priv->vifs, list) { + if (RWNX_VIF_TYPE(vif) == if_type) { + break; + } + } + if ((ret > 3) || (ret < 1)) { + printk("param error: cnt=%d\n", ret); + } else if (vif) { + struct ieee80211_channel chan_entry = {0,}; + struct ieee80211_channel *chan = &chan_entry; + struct mm_remain_on_channel_cfm roc_cfm; + if (ret < 3) { + duration = 2000; + if (ret < 2) { + chan_freq = 2412; + } + } + printk("set_roc: start=%d, freq=%d\n", roc_start, chan_freq); + if (roc_start) { + if (chan_freq <= 2484) { + chan->band = NL80211_BAND_2GHZ; + } else { + chan->band = NL80211_BAND_5GHZ; + } + chan->center_freq = chan_freq; + chan->max_power = 18; + ret = rwnx_send_roc(priv, vif, chan, duration, &roc_cfm); + if (ret) { + printk("rwnx_send_roc fail: %d\n", ret); + } else { + printk("roc_cfm: opcode=%x, st=%d, idx=%d\n", roc_cfm.op_code, roc_cfm.status, roc_cfm.chan_ctxt_index); + } + } else { + ret = rwnx_send_cancel_roc(priv); + if (ret) { + printk("rwnx_send_cancel_roc fail: %d\n", ret); + } + } + } + + return count; +} + +DEBUGFS_WRITE_FILE_OPS(set_roc); #ifdef CONFIG_RWNX_FULLMAC @@ -2239,6 +2375,8 @@ int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) DEBUGFS_ADD_FILE(regdbg, dir_drv, S_IWUSR); DEBUGFS_ADD_FILE(vendor_hwconfig, dir_drv,S_IWUSR); DEBUGFS_ADD_FILE(vendor_swconfig, dir_drv,S_IWUSR); + DEBUGFS_ADD_FILE(agg_disable, dir_drv,S_IWUSR); + DEBUGFS_ADD_FILE(set_roc, dir_drv,S_IWUSR); #ifdef CONFIG_RWNX_P2P_DEBUGFS { diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.c index b027b727f..8bacc6b03 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.c @@ -52,7 +52,10 @@ #include "aicwf_compat_8800dc.h" #include "aicwf_compat_8800d80.h" #include "rwnx_wakelock.h" - +#ifdef CONFIG_SDIO_BT +#include "aic_btsdio.h" +#endif +#include "aic_priv_cmd.h" #define RW_DRV_DESCRIPTION "RivieraWaves 11nac driver for Linux cfg80211" #define RW_DRV_COPYRIGHT "Copyright(c) 2015-2017 RivieraWaves" @@ -375,7 +378,11 @@ static const struct ieee80211_iface_combination rwnx_combinations[] = { { .limits = rwnx_limits, .n_limits = ARRAY_SIZE(rwnx_limits), +#ifdef CONFIG_MCC .num_different_channels = NX_CHAN_CTXT_CNT, +#else + .num_different_channels = 1, +#endif .max_interfaces = NX_VIRT_DEV_MAX, }, /* Keep this combination as the last one */ @@ -503,8 +510,7 @@ static const int rwnx_hwq2uapsd[NL80211_NUM_ACS] = { extern uint8_t scanning; -// int aicwf_dbg_level = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; -int aicwf_dbg_level = LOGERROR; +int aicwf_dbg_level = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; module_param(aicwf_dbg_level, int, 0660); int testmode = 0; char aic_fw_path[200]; @@ -972,8 +978,6 @@ static int rwnx_open(struct net_device *dev) #endif /* Device is now started */ - set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); - atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); } #ifdef CONFIG_COEX else if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) { @@ -981,6 +985,10 @@ static int rwnx_open(struct net_device *dev) } #endif + set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); + atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); + AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); + if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO) { if (!rwnx_hw->is_p2p_alive) { if (rwnx_hw->p2p_dev_vif && !rwnx_hw->p2p_dev_vif->up) { @@ -1003,8 +1011,10 @@ static int rwnx_open(struct net_device *dev) spin_unlock_bh(&rwnx_hw->cb_lock); } rwnx_hw->is_p2p_alive = 1; +#ifndef CONFIG_USE_P2P0 mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); +#endif } } @@ -1026,7 +1036,6 @@ static int rwnx_open(struct net_device *dev) } else { /* Forward the information to the LMAC, * p2p value not used in FMAC configuration, iftype is sufficient */ - error = rwnx_send_add_if (rwnx_hw, rwnx_vif->wdev.address, RWNX_VIF_TYPE(rwnx_vif), false, &add_if_cfm); if (error) { printk("add if fail\n"); @@ -1054,7 +1063,6 @@ static int rwnx_open(struct net_device *dev) rwnx_hw->is_p2p_alive = 1; } #endif - } if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_MONITOR) { @@ -1212,6 +1220,8 @@ static int rwnx_close(struct net_device *dev) } #ifdef CONFIG_USE_P2P0 if(!rwnx_vif->is_p2p_vif || ( rwnx_vif->is_p2p_vif && rwnx_hw->is_p2p_alive)){ + if (rwnx_vif->is_p2p_vif) + rwnx_hw->is_p2p_alive = 0; #endif rwnx_send_remove_if (rwnx_hw, rwnx_vif->vif_index, false); #ifdef CONFIG_USE_P2P0 @@ -1256,7 +1266,6 @@ static int rwnx_close(struct net_device *dev) } } #endif - clear_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); } #ifdef CONFIG_COEX else { @@ -1264,6 +1273,8 @@ static int rwnx_close(struct net_device *dev) rwnx_send_coex_req(rwnx_hw, 0, 1); } #endif + clear_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); + AICWFDBG(LOGDEBUG, "%s rwnx_vif->drv_flags:%d\r\n", __func__, (int)rwnx_vif->drv_flags); #ifdef CONFIG_GPIO_WAKEUP //open lp mode @@ -1280,1400 +1291,14 @@ static int rwnx_close(struct net_device *dev) return 0; } -#ifdef CONFIG_RFTEST -enum { - SET_TX, - SET_TXSTOP, - SET_TXTONE, - SET_RX, - GET_RX_RESULT, - SET_RXSTOP, - SET_RXMETER, - SET_POWER, - SET_XTAL_CAP, - SET_XTAL_CAP_FINE, - GET_EFUSE, - SET_FREQ_CAL, - SET_FREQ_CAL_FINE, - GET_FREQ_CAL, - SET_MAC_ADDR, - GET_MAC_ADDR, - SET_BT_MAC_ADDR, - GET_BT_MAC_ADDR, - SET_VENDOR_INFO, - GET_VENDOR_INFO, - RDWR_PWRMM, - RDWR_PWRIDX, - RDWR_PWRLVL = RDWR_PWRIDX, - RDWR_PWROFST, - RDWR_DRVIBIT, - RDWR_EFUSE_PWROFST, - RDWR_EFUSE_DRVIBIT, - SET_PAPR, - SET_CAL_XTAL, - GET_CAL_XTAL_RES, - SET_COB_CAL, - GET_COB_CAL_RES, - RDWR_EFUSE_USRDATA, - SET_NOTCH, - RDWR_PWROFSTFINE, - RDWR_EFUSE_PWROFSTFINE, - RDWR_EFUSE_SDIOCFG, - RDWR_EFUSE_USBVIDPID, -}; - -typedef struct { - u8_l chan; - u8_l bw; - u8_l mode; - u8_l rate; - u16_l length; - u16_l tx_intv_us; -} cmd_rf_settx_t; - -typedef struct { - u8_l val; -} cmd_rf_setfreq_t; - -typedef struct { - u8_l chan; - u8_l bw; -} cmd_rf_rx_t; - -typedef struct { - u8_l block; -} cmd_rf_getefuse_t; -typedef struct -{ - u8_l dutid; - u8_l chip_num; - u8_l dis_xtal; -}cmd_rf_setcobcal_t; -typedef struct - { - u16_l dut_rcv_golden_num; - u8_l golden_rcv_dut_num; - s8_l rssi_static; - s8_l snr_static; - s8_l dut_rssi_static; - u16_l reserved; - }cob_result_ptr_t; -#endif - -#define CMD_MAXARGS 10 - -#if 0 -#define isblank(c) ((c) == ' ' || (c) == '\t') -#define isascii(c) (((unsigned char)(c)) <= 0x7F) - -static int isdigit(unsigned char c) -{ - return ((c >= '0') && (c <= '9')); -} - -static int isxdigit(unsigned char c) -{ - if ((c >= '0') && (c <= '9')) - return 1; - if ((c >= 'a') && (c <= 'f')) - return 1; - if ((c >= 'A') && (c <= 'F')) - return 1; - return 0; -} - -static int islower(unsigned char c) -{ - return ((c >= 'a') && (c <= 'z')); -} - -static unsigned char toupper(unsigned char c) -{ - if (islower(c)) - c -= 'a' - 'A'; - return c; -} -#endif - - -static int parse_line (char *line, char *argv[]) -{ - int nargs = 0; - - while (nargs < CMD_MAXARGS) { - /* skip any white space */ - while ((*line == ' ') || (*line == '\t')) { - ++line; - } - - if (*line == '\0') { /* end of line, no more args */ - argv[nargs] = 0; - return nargs; - } - - /* Argument include space should be bracketed by quotation mark */ - if (*line == '\"') { - /* Skip quotation mark */ - line++; - - /* Begin of argument string */ - argv[nargs++] = line; - - /* Until end of argument */ - while (*line && (*line != '\"')) { - ++line; - } - } else { - argv[nargs++] = line; /* begin of argument string */ - - /* find end of string */ - while (*line && (*line != ' ') && (*line != '\t')) { - ++line; - } - } - - if (*line == '\0') { /* end of line, no more args */ - argv[nargs] = 0; - return nargs; - } - - *line++ = '\0'; /* terminate current arg */ - } - - printk("** Too many args (max. %d) **\n", CMD_MAXARGS); - - return nargs; -} - -unsigned int command_strtoul(const char *cp, char **endp, unsigned int base) -{ - unsigned int result = 0, value, is_neg = 0; - - if (*cp == '0') { - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - base = 16; - cp++; - } - if (!base) { - base = 8; - } - } - if (!base) { - base = 10; - } - if (*cp == '-') { - is_neg = 1; - cp++; - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { - result = result * base + value; - cp++; - } - if (is_neg) - result = (unsigned int)((int)result * (-1)); - - if (endp) - *endp = (char *)cp; - return result; -} - - -int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) -{ - int bytes_written = 0; - char *para = NULL; - char *cmd = NULL; - char *argv[CMD_MAXARGS + 1]; - int argc; -#ifdef CONFIG_RFTEST - struct dbg_rftest_cmd_cfm cfm; - u8_l mac_addr[6]; - cmd_rf_settx_t settx_param; - cmd_rf_rx_t setrx_param; - int freq; - cmd_rf_getefuse_t getefuse_param; - cmd_rf_setfreq_t cmd_setfreq; - cmd_rf_setcobcal_t setcob_cal; - u8_l ana_pwr; - u8_l dig_pwr; - u8_l pwr; - u8_l xtal_cap; - u8_l xtal_cap_fine; - u8_l vendor_info; - cob_result_ptr_t *cob_result_ptr; - -#endif - - u8_l state; - -#ifdef CONFIG_GPIO_WAKEUP - u8_l setsusp_mode; - int ret = 0; -#endif - - RWNX_DBG(RWNX_FN_ENTRY_STR); - - argc = parse_line(command, argv); - if (argc == 0) { - return -1; - } - - do { -#ifdef CONFIG_RFTEST - if (strcasecmp(argv[0], "GET_RX_RESULT") == 0) { - AICWFDBG(LOGINFO, "get_rx_result\n"); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 8); - bytes_written = 8; - } else if (strcasecmp(argv[0], "SET_TX") == 0) { - AICWFDBG(LOGINFO, "set_tx\n"); - if (argc < 6) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - settx_param.chan = command_strtoul(argv[1], NULL, 10); - settx_param.bw = command_strtoul(argv[2], NULL, 10); - settx_param.mode = command_strtoul(argv[3], NULL, 10); - settx_param.rate = command_strtoul(argv[4], NULL, 10); - settx_param.length = command_strtoul(argv[5], NULL, 10); - if (argc > 6) { - settx_param.tx_intv_us = command_strtoul(argv[6], NULL, 10); - } else { - settx_param.tx_intv_us = 0; - } - AICWFDBG(LOGINFO, "txparam:%d,%d,%d,%d,%d,%d\n", settx_param.chan, settx_param.bw, - settx_param.mode, settx_param.rate, settx_param.length, settx_param.tx_intv_us); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); - #endif - } else if (strcasecmp(argv[0], "SET_TXSTOP") == 0) { - AICWFDBG(LOGINFO, "settx_stop\n"); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_TXSTOP, 0, NULL, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_TXSTOP, 0, NULL, NULL); - #endif - } else if (strcasecmp(argv[0], "SET_TXTONE") == 0) { - AICWFDBG(LOGINFO, "set_tx_tone,argc:%d\n", argc); - if ((argc == 2) || (argc == 3)) { - u8_l func, buf[2]; - s8_l freq; - AICWFDBG(LOGINFO, "argv 1:%s\n", argv[1]); - func = (u8_l)command_strtoul(argv[1], NULL, 16); - if (argc == 3) { - AICWFDBG(LOGINFO, "argv 2:%s\n", argv[2]); - freq = (u8_l)command_strtoul(argv[2], NULL, 10); - } else { - freq = 0; - } - buf[0] = func; - buf[1] = (u8_l)freq; - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - } - } else if (strcasecmp(argv[0], "SET_RX") == 0) { - AICWFDBG(LOGINFO, "set_rx\n"); - if (argc < 3) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - setrx_param.chan = command_strtoul(argv[1], NULL, 10); - setrx_param.bw = command_strtoul(argv[2], NULL, 10); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); - #endif - } else if (strcasecmp(argv[0], "SET_RXSTOP") == 0) { - AICWFDBG(LOGINFO, "set_rxstop\n"); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_RXSTOP, 0, NULL, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_RXSTOP, 0, NULL, NULL); - #endif - } else if (strcasecmp(argv[0], "SET_RX_METER") == 0) { - AICWFDBG(LOGINFO, "set_rx_meter\n"); - freq = (int)command_strtoul(argv[1], NULL, 10); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_RXMETER, sizeof(freq), (u8_l *)&freq, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_RXMETER, sizeof(freq), (u8_l *)&freq, NULL); - #endif - } else if (strcasecmp(argv[0], "SET_FREQ_CAL") == 0) { - AICWFDBG(LOGINFO, "set_freq_cal\n"); - if (argc < 2) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); - AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "SET_FREQ_CAL_FINE") == 0) { - AICWFDBG(LOGINFO, "set_freq_cal_fine\n"); - if (argc < 2) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); - AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "GET_EFUSE") == 0) { - AICWFDBG(LOGINFO, "get_efuse\n"); - if (argc < 2) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - getefuse_param.block = command_strtoul(argv[1], NULL, 10); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_EFUSE, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_EFUSE, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); - #endif - AICWFDBG(LOGINFO, "get val=%x\r\n", cfm.rftest_result[0]); - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "SET_POWER") == 0) { - AICWFDBG(LOGINFO, "set_power\n"); - if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) { - ana_pwr = command_strtoul(argv[1], NULL, 16); - dig_pwr = command_strtoul(argv[2], NULL, 16); - pwr = (ana_pwr << 4 | dig_pwr); - if (ana_pwr > 0xf || dig_pwr > 0xf) { - AICWFDBG(LOGERROR, "invalid param\r\n"); - bytes_written = -EINVAL; - break; - } - } else { - ana_pwr = command_strtoul(argv[1], NULL, 10); - pwr = ana_pwr; - if (ana_pwr > 0x1e) { - AICWFDBG(LOGERROR, "invalid param\r\n"); - bytes_written = -EINVAL; - break; - } - } - AICWFDBG(LOGINFO, "pwr =%x\r\n", pwr); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); - #endif - } else if (strcasecmp(argv[0], "SET_XTAL_CAP") == 0) { - AICWFDBG(LOGINFO, "set_xtal_cap\n"); - if (argc < 2) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - xtal_cap = command_strtoul(argv[1], NULL, 10); - AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "SET_XTAL_CAP_FINE") == 0) { - AICWFDBG(LOGINFO, "set_xtal_cap_fine\n"); - if (argc < 2) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - xtal_cap_fine = command_strtoul(argv[1], NULL, 10); - AICWFDBG(LOGINFO, "xtal_cap_fine =%x\r\n", xtal_cap_fine); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "SET_MAC_ADDR") == 0) { - printk("set_mac_addr\n"); - if (argc < 7) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - mac_addr[5] = command_strtoul(argv[1], NULL, 16); - mac_addr[4] = command_strtoul(argv[2], NULL, 16); - mac_addr[3] = command_strtoul(argv[3], NULL, 16); - mac_addr[2] = command_strtoul(argv[4], NULL, 16); - mac_addr[1] = command_strtoul(argv[5], NULL, 16); - mac_addr[0] = command_strtoul(argv[6], NULL, 16); - AICWFDBG(LOGINFO, "set macaddr:%x,%x,%x,%x,%x,%x\n", mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); - #endif - } else if (strcasecmp(argv[0], "GET_MAC_ADDR") == 0) { - u32_l addr0, addr1; - AICWFDBG(LOGINFO, "get mac addr\n"); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 8); - bytes_written = 8; - addr0 = cfm.rftest_result[0]; - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { - int rem_cnt = (cfm.rftest_result[1] >> 16) & 0x00FF; - addr1 = cfm.rftest_result[1] & 0x0000FFFF; - AICWFDBG(LOGINFO, "0x%x,0x%x (remain:%x)\n", addr0, addr1, rem_cnt); - } else { - addr1 = cfm.rftest_result[1]; - AICWFDBG(LOGINFO, "0x%x,0x%x\n", addr0, addr1); - } - } else if (strcasecmp(argv[0], "SET_VENDOR_INFO") == 0) { - vendor_info = command_strtoul(argv[1], NULL, 16); - AICWFDBG(LOGINFO, "set vendor info:%x\n", vendor_info); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); - #endif - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { - memcpy(command, &cfm.rftest_result[0], 2); - bytes_written = 2; - } else { - memcpy(command, &cfm.rftest_result[0], 1); - bytes_written = 1; - } - AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); - } else if (strcasecmp(argv[0], "GET_VENDOR_INFO") == 0) { - AICWFDBG(LOGINFO, "get vendor info\n"); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); - #endif - #ifdef AICWF_USB_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); - #endif - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { - memcpy(command, &cfm.rftest_result[0], 2); - bytes_written = 2; - } else { - memcpy(command, &cfm.rftest_result[0], 1); - bytes_written = 1; - } - AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); - } else if (strcasecmp(argv[0], "GET_FREQ_CAL") == 0) { - unsigned int val; - AICWFDBG(LOGINFO, "get freq cal\n"); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm); - #endif - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - val = cfm.rftest_result[0]; - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { - AICWFDBG(LOGINFO, "cap=0x%x (remain:%x), cap_fine=%x (remain:%x)\n", - val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); - } else { - AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", val & 0xff, (val >> 8) & 0xff); - } - } else if (strcasecmp(argv[0], "RDWR_PWRMM") == 0) { - AICWFDBG(LOGINFO, "read/write txpwr manul mode\n"); - if (argc <= 1) { // read cur - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRMM, 0, NULL, &cfm); - #endif - } else { // write - u8_l pwrmm = (u8_l)command_strtoul(argv[1], NULL, 16); - pwrmm = (pwrmm) ? 1 : 0; - AICWFDBG(LOGINFO, "set pwrmm = %x\r\n", pwrmm); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRMM, sizeof(pwrmm), (u8_l *)&pwrmm, &cfm); - #endif - } - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "RDWR_PWRIDX") == 0) { - u8_l func = 0; - #ifdef AICWF_SDIO_SUPPORT - if (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8801) { - AICWFDBG(LOGERROR, "unsupported cmd\n"); - bytes_written = -EINVAL; - break; - } - #endif - AICWFDBG(LOGINFO, "read/write txpwr index\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRIDX, 0, NULL, &cfm); - #endif - } else if (func <= 2) { // write 2.4g/5g pwr idx - if (argc > 3) { - u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l pwridx = (u8_l)command_strtoul(argv[3], NULL, 10); - u8_l buf[3] = {func, type, pwridx}; - AICWFDBG(LOGINFO, "set pwridx:[%x][%x]=%x\r\n", func, type, pwridx); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRIDX, sizeof(buf), buf, &cfm); - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - memcpy(command, &cfm.rftest_result[0], 9); - bytes_written = 9; - } else if (strcasecmp(argv[0], "RDWR_PWRLVL") == 0) { - u8_l func = 0; - #ifdef AICWF_SDIO_SUPPORT - if ((g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800DC) - && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800DW) - && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800D80)) { - AICWFDBG(LOGINFO, "unsupported cmd\n"); - bytes_written = -EINVAL; - break; - } - #endif - AICWFDBG(LOGINFO, "read/write txpwr level\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRLVL, 0, NULL, &cfm); - } else if (func <= 2) { // write 2.4g/5g pwr lvl - if (argc > 4) { - u8_l grp = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l idx, size; - u8_l buf[14] = {func, grp,}; - if (argc > 12) { // set all grp - AICWFDBG(LOGINFO, "set pwrlvl %s:\n" - " [%x] =", (func == 1) ? "2.4g" : "5g", grp); - if (grp == 1) { // TXPWR_LVL_GRP_11N_11AC - size = 10; - } else { - size = 12; - } - for (idx = 0; idx < size; idx++) { - s8_l pwrlvl = (s8_l)command_strtoul(argv[3 + idx], NULL, 10); - buf[2 + idx] = (u8_l)pwrlvl; - if (idx && !(idx & 0x3)) { - AICWFDBG(LOGINFO, " "); - } - AICWFDBG(LOGINFO, " %2d", pwrlvl); - } - AICWFDBG(LOGINFO, "\n"); - size += 2; - } else { // set grp[idx] - u8_l idx = (u8_l)command_strtoul(argv[3], NULL, 10); - s8_l pwrlvl = (s8_l)command_strtoul(argv[4], NULL, 10); - buf[2] = idx; - buf[3] = (u8_l)pwrlvl; - size = 4; - AICWFDBG(LOGINFO, "set pwrlvl %s:\n" - " [%x][%d] = %d\n", (func == 1) ? "2.4g" : "5g", grp, idx, pwrlvl); - } - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRLVL, size, buf, &cfm); - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ - memcpy(command, &cfm.rftest_result[0], 6 * 12); - bytes_written = 6 * 12; - } else { - memcpy(command, &cfm.rftest_result[0], 3 * 12); - bytes_written = 3 * 12; - } - } else if (strcasecmp(argv[0], "RDWR_PWROFST") == 0) { - u8_l func = 0; - int res_len = 0; - AICWFDBG(LOGINFO, "read/write txpwr offset\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm); - #endif - } else if (func <= 2) { // write 2.4g/5g pwr ofst - if ((argc > 4) && (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80)) { - u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); - s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); - u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; - printk("set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); - #endif - } else if ((argc > 3) && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800D80)) { - u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); - s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); - u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; - printk("set pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { // 3 = 3 (2.4g) - res_len = 3; - } else if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) - res_len = 3 * 3 + 3 * 6; - } else { - res_len = 3 + 4; - } - memcpy(command, &cfm.rftest_result[0], res_len); - bytes_written = res_len; - } else if (strcasecmp(argv[0], "RDWR_PWROFSTFINE") == 0) { - u8_l func = 0; - AICWFDBG(LOGINFO, "read/write txpwr offset fine\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFSTFINE, 0, NULL, &cfm); - } else if (func <= 2) { // write 2.4g/5g pwr ofst - if (argc > 3) { - u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); - s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); - u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; - AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm); - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - memcpy(command, &cfm.rftest_result[0], 7); - bytes_written = 7; - } else if (strcasecmp(argv[0], "RDWR_DRVIBIT") == 0) { - u8_l func = 0; - AICWFDBG(LOGINFO, "read/write pa drv_ibit\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_DRVIBIT, 0, NULL, &cfm); - #endif - } else if (func == 1) { // write 2.4g pa drv_ibit - if (argc > 2) { - u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l buf[2] = {func, ibit}; - printk("set drvibit:[%x]=%x\r\n", func, ibit); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_DRVIBIT, sizeof(buf), buf, &cfm); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - memcpy(command, &cfm.rftest_result[0], 16); - bytes_written = 16; - } else if (strcasecmp(argv[0], "RDWR_EFUSE_PWROFST") == 0) { - u8_l func = 0; - int res_len = 0; - AICWFDBG(LOGINFO, "read/write txpwr offset into efuse\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm); - #endif - } else if (func <= 2) { // write 2.4g/5g pwr ofst - if ((argc > 4) && (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80)) { - u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16); - s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10); - u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst}; - printk("set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); - #endif - } else if ((argc > 3) && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800D80)) { - u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); - s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); - u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; - printk("set efuse pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 - res_len = 3 * 2; - } else if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) - res_len = 3 * 3 + 3 * 6; - } else { // 7 = 3(2.4g) + 4(5g) - res_len = 3 + 4; - } - memcpy(command, &cfm.rftest_result[0], res_len); - bytes_written = res_len; - } else if (strcasecmp(argv[0], "RDWR_EFUSE_DRVIBIT") == 0) { - u8_l func = 0; - AICWFDBG(LOGINFO, "read/write pa drv_ibit into efuse\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_DRVIBIT, 0, NULL, &cfm); - #endif - } else if (func == 1) { // write 2.4g pa drv_ibit - if (argc > 2) { - u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l buf[2] = {func, ibit}; - AICWFDBG(LOGINFO, "set efuse drvibit:[%x]=%x\r\n", func, ibit); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_DRVIBIT, sizeof(buf), buf, &cfm); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "RDWR_EFUSE_PWROFSTFINE") == 0) { - u8_l func = 0; - AICWFDBG(LOGINFO, "read/write txpwr offset fine into efuse\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFSTFINE, 0, NULL, &cfm); - } else if (func <= 2) { // write 2.4g/5g pwr ofst - if (argc > 3) { - u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16); - s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10); - u8_l buf[3] = {func, chgrp, (u8_l)pwrofst}; - AICWFDBG(LOGINFO, "set efuse pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm); - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 - memcpy(command, &cfm.rftest_result[0], 6); - bytes_written = 6; - } else { // 7 = 3(2.4g) + 4(5g) - memcpy(command, &cfm.rftest_result[0], 7); - bytes_written = 7; - } - } else if (strcasecmp(argv[0], "SET_PAPR") == 0) { - AICWFDBG(LOGINFO, "set papr\n"); - if (argc > 1) { - u8_l func = (u8_l) command_strtoul(argv[1], NULL, 10); - AICWFDBG(LOGINFO, "papr %d\r\n", func); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_PAPR, sizeof(func), &func, NULL); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else if (strcasecmp(argv[0], "SET_NOTCH") == 0) { - if (argc > 1) { - u8_l func = (u8_l) command_strtoul(argv[1], NULL, 10); - AICWFDBG(LOGINFO, "set notch %d\r\n", func); - #ifdef AICWF_SDIO_SUPPORT - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_NOTCH, sizeof(func), &func, NULL); - #endif - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else if (strcasecmp(argv[0], "SET_COB_CAL") == 0) { - AICWFDBG(LOGINFO, "set_cob_cal\n"); - if (argc < 3) { - AICWFDBG(LOGERROR, "wrong param\n"); - bytes_written = -EINVAL; - break; - } - setcob_cal.dutid = command_strtoul(argv[1], NULL, 10); - setcob_cal.chip_num = command_strtoul(argv[2], NULL, 10); - setcob_cal.dis_xtal = command_strtoul(argv[3], NULL, 10); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); - } else if (strcasecmp(argv[0], "GET_COB_CAL_RES")==0) { - AICWFDBG(LOGINFO, "get cob cal res\n"); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", cfm.rftest_result[0] & 0x0000ffff, (cfm.rftest_result[0] >> 16) & 0x0000ffff); - } else if (strcasecmp(argv[0], "DO_COB_TEST") == 0) { - AICWFDBG(LOGINFO, "do_cob_test\n"); - setcob_cal.dutid = 1; - setcob_cal.chip_num = 1; - setcob_cal.dis_xtal = 0; - if (argc > 1 ) { - setcob_cal.dis_xtal = command_strtoul(argv[1], NULL, 10); - } - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); - msleep(2000); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); - state = (cfm.rftest_result[0] >> 16) & 0x000000ff; - if (!state){ - AICWFDBG(LOGINFO, "cap= 0x%x, cap_fine= 0x%x, freq_ofst= %d Hz\n", - cfm.rftest_result[0] & 0x000000ff, (cfm.rftest_result[0] >> 8) & 0x000000ff, cfm.rftest_result[1]); - cob_result_ptr = (cob_result_ptr_t *) & (cfm.rftest_result[2]); - AICWFDBG(LOGINFO, "golden_rcv_dut= %d , tx_rssi= %d dBm, snr = %d dB\ndut_rcv_godlden= %d , rx_rssi= %d dBm", - cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, - cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static); - memcpy(command, &cfm.rftest_result, 16); - bytes_written = 16; - } else { - AICWFDBG(LOGERROR, "cob not idle\n"); - bytes_written = -EINVAL; - break; - } - } else if (strcasecmp(argv[0], "RDWR_EFUSE_SDIOCFG") == 0) { - u8_l func = 0; - AICWFDBG(LOGINFO, "read/write sdiocfg_bit into efuse\n"); - if (argc > 1) { - func = (u8_l)command_strtoul(argv[1], NULL, 16); - } - if (func == 0) { // read cur - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_SDIOCFG, 0, NULL, &cfm); - } else if (func == 1) { // write sdiocfg - if (argc > 2) { - u8_l ibit = (u8_l)command_strtoul(argv[2], NULL, 16); - u8_l buf[2] = {func, ibit}; - AICWFDBG(LOGINFO, "set efuse sdiocfg:[%x]=%x\r\n", func, ibit); - rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_SDIOCFG, sizeof(buf), buf, &cfm); - } else { - AICWFDBG(LOGERROR, "wrong args\n"); - bytes_written = -EINVAL; - break; - } - } else { - AICWFDBG(LOGERROR, "wrong func: %x\n", func); - bytes_written = -EINVAL; - break; - } - memcpy(command, &cfm.rftest_result[0], 4); - bytes_written = 4; - } else if (strcasecmp(argv[0], "SETSUSPENDMODE") == 0 && testmode == 0) { - #ifdef AICWF_SDIO_SUPPORT - #ifdef CONFIG_GPIO_WAKEUP - setsusp_mode = command_strtoul(argv[1], NULL, 10); - rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode); - if (setsusp_mode == 1) { - #if defined(CONFIG_SDIO_PWRCTRL) - aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); - #endif - - ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); - if (ret < 0) { - sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); - } - } - AICWFDBG(LOGINFO, "set suspend mode %d\n", setsusp_mode); - #endif//CONFIG_GPIO_WAKEUP - #endif - } else { - AICWFDBG(LOGERROR, "wrong cmd:%s in %s\n", cmd, __func__); - bytes_written = -EINVAL; - } -#endif - } while (0); - kfree(cmd); - kfree(para); - return bytes_written; -} - -//Android private command - -#define RWNX_COUNTRY_CODE_LEN 2 -#define CMD_SET_COUNTRY "COUNTRY" -#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE" -#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" - -struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2); -struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy, int index); -extern int reg_regdb_size; - -#ifdef CONFIG_SET_VENDOR_EXTENSION_IE -extern u8_l vendor_extension_data[256]; -extern int vendor_extension_len; - -void set_vendor_extension_ie(char *command){ - - char databyte[3]={0x00, 0x00, 0x00}; - int skip = strlen(CMD_SET_VENDOR_EX_IE) + 1; - int command_index = skip; - int data_index = 0; - - memset(vendor_extension_data, 0, 256); - vendor_extension_len = 0; - memcpy(databyte, command + command_index, 2); - vendor_extension_len = command_strtoul(databyte, NULL, 16); - printk("%s len:%d \r\n", __func__, vendor_extension_len); - - //parser command and save data in vendor_extension_data - for(data_index = 0;data_index < vendor_extension_len; data_index++){ - command_index = command_index + 3; - memcpy(databyte, command + command_index, 2); - vendor_extension_data[data_index] = command_strtoul(databyte, NULL, 16); - } - -} -#endif//CONFIG_SET_VENDOR_EXTENSION_IE - - -int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) -{ -#define PRIVATE_COMMAND_MAX_LEN 8192 -#define PRIVATE_COMMAND_DEF_LEN 4096 - - struct rwnx_vif *vif = netdev_priv(net); - int ret = 0; - char *command = NULL; - int bytes_written = 0; - android_wifi_priv_cmd priv_cmd; - int buf_size = 0; - int skip = 0; - char *country = NULL; - struct ieee80211_regdomain *regdomain; - - RWNX_DBG(RWNX_FN_ENTRY_STR); - - ///todo: add our lock - //net_os_wake_lock(net); - - -/* if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto exit; - }*/ - if (!ifr->ifr_data) { - ret = -EINVAL; - goto exit; - } - -#ifdef CONFIG_COMPAT -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) - if (in_compat_syscall()) -#else - if (is_compat_task()) -#endif - { - compat_android_wifi_priv_cmd compat_priv_cmd; - if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { - ret = -EFAULT; - goto exit; - } - priv_cmd.buf = compat_ptr(compat_priv_cmd.buf); - priv_cmd.used_len = compat_priv_cmd.used_len; - priv_cmd.total_len = compat_priv_cmd.total_len; - } else -#endif /* CONFIG_COMPAT */ - { - if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { - ret = -EFAULT; - goto exit; - } - } - if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { - printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); - ret = -EINVAL; - goto exit; - } - - buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); - command = kmalloc((buf_size + 1), GFP_KERNEL); - - if (!command) { - printk("%s: failed to allocate memory\n", __FUNCTION__); - ret = -ENOMEM; - goto exit; - } - if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { - ret = -EFAULT; - goto exit; - } - command[priv_cmd.total_len] = '\0'; - - /* outputs */ - AICWFDBG(LOGINFO, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); - AICWFDBG(LOGINFO, "cmd = %d\n", cmd); - AICWFDBG(LOGINFO, "buf_size=%d\n", buf_size); - -#if 1//Handle Android command - if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY))) { - skip = strlen(CMD_SET_COUNTRY) + 1; - country = command + skip; - if (!country || strlen(country) < RWNX_COUNTRY_CODE_LEN) { - printk("%s: invalid country code\n", __func__); - ret = -EINVAL; - goto exit; - } -#if 0 - for(index = 0; index < reg_regdb_size; index++){ - regdomain = getRegdomainFromRwnxDBIndex(vif->rwnx_hw->wiphy, index); - if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ - printk("regulatory_set_wiphy_regd fail \r\n"); - }else{ - printk("regulatory_set_wiphy_regd ok \r\n"); - } - } -#endif - AICWFDBG(LOGINFO, "%s country code:%c%c\n", __func__, toupper(country[0]), toupper(country[1])); - regdomain = getRegdomainFromRwnxDB(vif->rwnx_hw->wiphy, country); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) - if((ret = regulatory_set_wiphy_regd(vif->rwnx_hw->wiphy, regdomain))){ - printk("regulatory_set_wiphy_regd fail \r\n"); - } -#else - wiphy_apply_custom_regulatory(vif->rwnx_hw->wiphy, regdomain); -#endif - } -#ifdef CONFIG_SET_VENDOR_EXTENSION_IE - else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){ - set_vendor_extension_ie(command); - } -#endif//CONFIG_SET_VENDOR_EXTENSION_IE - else if(!strncasecmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE))){ - ret = 0; - goto exit; - } -#endif//Handle Android command - - bytes_written = handle_private_cmd(net, command, priv_cmd.total_len); - if (bytes_written >= 0) { - if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { - command[0] = '\0'; - } - if (bytes_written >= priv_cmd.total_len) { - printk("%s: err. bytes_written:%d >= buf_size:%d \n", - __FUNCTION__, bytes_written, buf_size); - goto exit; - } - bytes_written++; - priv_cmd.used_len = bytes_written; - if (copy_to_user(priv_cmd.buf, command, bytes_written)) { - printk("%s: failed to copy data to user buffer\n", __FUNCTION__); - ret = -EFAULT; - } - } else { - /* Propagate the error */ - ret = bytes_written; - } - -exit: - ///todo: add our unlock - //net_os_wake_unlock(net); - kfree(command); - return ret; -} - -#ifdef CONFIG_MCU_MESSAGE -#define CMD_GET_VERSION_STR "GET_VERSION" -#define CMD_GET_SSID_STR "GET_SSID" -#define CMD_SET_SSID_STR "SET_SSID" -#define CMD_GET_PASS_STR "GET_PASS" -#define CMD_SET_PASS_STR "SET_PASS" -#define CMD_GET_VAR_STR "GET_VAR" -#define CMD_SET_VAR_STR "SET_VAR" - -enum custmsg_cmd_tag -{ - CUST_CMD_GET_VERSION = 0, - CUST_CMD_GET_SSID, - CUST_CMD_SET_SSID, - CUST_CMD_GET_PASS, - CUST_CMD_SET_PASS, - CUST_CMD_GET_VAR, - CUST_CMD_SET_VAR, - CUST_CMD_MAX -}; - -int handle_custom_msg(char *command, u32 cmd_len) -{ - int bytes_read = 0, max_bytes_to_read = 0; - struct rwnx_hw *p_rwnx_hw = NULL; - u32 cmd, len = 0, flags = 0; - char *buf = NULL; - struct dbg_custom_msg_cfm *cust_msg_cfm; - printk("cmd,%s,%ld\n",command,strlen(command)); - if (strncasecmp(command, CMD_GET_VERSION_STR, strlen(CMD_GET_VERSION_STR)) == 0) { - cmd = CUST_CMD_GET_VERSION; - max_bytes_to_read = 32; // max str len for version - } else if (strncasecmp(command, CMD_GET_SSID_STR, strlen(CMD_GET_SSID_STR)) == 0) { - cmd = CUST_CMD_GET_SSID; - max_bytes_to_read = 48; // max str len for ssid - } else if (strncasecmp(command, CMD_SET_SSID_STR, strlen(CMD_SET_SSID_STR)) == 0) { - cmd = CUST_CMD_SET_SSID; - len = cmd_len - (strlen(CMD_SET_SSID_STR) + 1); - buf = command + (strlen(CMD_SET_SSID_STR) + 1); - max_bytes_to_read = 0; - } else if (strncasecmp(command, CMD_GET_PASS_STR, strlen(CMD_GET_PASS_STR)) == 0) { - cmd = CUST_CMD_GET_PASS; - max_bytes_to_read = 64; // max str len for PASS - } else if (strncasecmp(command, CMD_SET_PASS_STR, strlen(CMD_SET_PASS_STR)) == 0) { - cmd = CUST_CMD_SET_PASS; - len = cmd_len - (strlen(CMD_SET_PASS_STR) + 1); - buf = command + (strlen(CMD_SET_PASS_STR) + 1); - max_bytes_to_read = 0; - } else if (strncasecmp(command, CMD_GET_VAR_STR, strlen(CMD_GET_VAR_STR)) == 0) { - cmd = CUST_CMD_GET_VAR; - max_bytes_to_read = 64; // max str len for VAR - } else if (strncasecmp(command, CMD_SET_VAR_STR, strlen(CMD_SET_VAR_STR)) == 0) { - cmd = CUST_CMD_SET_VAR; - len = cmd_len - (strlen(CMD_SET_VAR_STR) + 1); - buf = command + (strlen(CMD_SET_VAR_STR) + 1); - max_bytes_to_read = 0; - } else { - printk("invalid cmd: %s\r\n", command); - return -1; - } - if (len < 0) { - printk("invalid len: %d\r\n", len); - return -3; - } - #ifdef AICWF_SDIO_SUPPORT - p_rwnx_hw = g_rwnx_plat->sdiodev->rwnx_hw; - #endif - #ifdef AICWF_USB_SUPPORT - p_rwnx_hw = g_rwnx_plat->usbdev->rwnx_hw; - #endif - cust_msg_cfm = (struct dbg_custom_msg_cfm *)kmalloc((offsetof(struct dbg_custom_msg_cfm, buf) + max_bytes_to_read), GFP_KERNEL); - if (cust_msg_cfm == NULL) { - printk("msg cfm alloc fail\r\n"); - return -2; - } - rwnx_send_dbg_custom_msg_req(p_rwnx_hw, cmd, buf, len, flags, cust_msg_cfm); - bytes_read = cust_msg_cfm->len; - printk("Custom msg cfm: cmd=%d, len=%d, status=%x\n", cust_msg_cfm->cmd, bytes_read, cust_msg_cfm->status); - if (bytes_read) { - memcpy(command, cust_msg_cfm->buf, bytes_read); - command[bytes_read] = '\0'; - } else { - command[0] = '\0'; - } - if (cust_msg_cfm->status) { - printk("cfm status: %x", cust_msg_cfm->status); - } - return bytes_read; -} - -int devipc_cust_msg(struct net_device *net, struct ifreq *ifr, int cmd) -{ -#ifdef PRIVATE_COMMAND_MAX_LEN -#undef PRIVATE_COMMAND_MAX_LEN -#undef PRIVATE_COMMAND_DEF_LEN -#define PRIVATE_COMMAND_MAX_LEN 8192 -#define PRIVATE_COMMAND_DEF_LEN 4096 -#endif - int ret = 0; - char *command = NULL; - int bytes_written = 0; - android_wifi_priv_cmd priv_cmd; - int buf_size = 0; - - RWNX_DBG(RWNX_FN_ENTRY_STR); - - ///todo: add our lock - //net_os_wake_lock(net); - - -/* if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto exit; - }*/ - if (!ifr->ifr_data) { - ret = -EINVAL; - goto exit; - } - -#ifdef CONFIG_COMPAT -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) - if (in_compat_syscall()) -#else - if (is_compat_task()) -#endif - { - compat_android_wifi_priv_cmd compat_priv_cmd; - if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) { - ret = -EFAULT; - goto exit; - } - priv_cmd.buf = compat_ptr(compat_priv_cmd.buf); - priv_cmd.used_len = compat_priv_cmd.used_len; - priv_cmd.total_len = compat_priv_cmd.total_len; - } else -#endif /* CONFIG_COMPAT */ - { - if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { - ret = -EFAULT; - goto exit; - } - } - if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { - printk("%s: buf length invalid:%d\n", __FUNCTION__, priv_cmd.total_len); - ret = -EINVAL; - goto exit; - } - - buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); - command = kmalloc((buf_size + 1), GFP_KERNEL); - - if (!command) - { - printk("%s: failed to allocate memory\n", __FUNCTION__); - ret = -ENOMEM; - goto exit; - } - if (copy_from_user(command, priv_cmd.buf, priv_cmd.used_len)) { - ret = -EFAULT; - goto exit; - } - command[priv_cmd.used_len] = '\0'; - - /* outputs */ - printk("%s: Devipc custom msg \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); - printk("cmd = %x\n", cmd); - printk("buf_size=%d\n", buf_size); - - - bytes_written = handle_custom_msg(command, priv_cmd.used_len); - if (bytes_written >= 0) { - if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { - command[0] = '\0'; - } - if (bytes_written >= priv_cmd.total_len) { - printk("%s: err. bytes_written:%d >= buf_size:%d \n", - __FUNCTION__, bytes_written, buf_size); - goto exit; - } - bytes_written++; - priv_cmd.used_len = bytes_written; - if (copy_to_user(priv_cmd.buf, command, bytes_written)) { - printk("%s: failed to copy data to user buffer\n", __FUNCTION__); - ret = -EFAULT; - } - } - else { - /* Propagate the error */ - ret = bytes_written; - } - -exit: - ///todo: add our unlock - //net_os_wake_unlock(net); - kfree(command); - return ret; -} -#endif - - #define IOCTL_HOSTAPD (SIOCIWFIRSTPRIV+28) #define IOCTL_WPAS (SIOCIWFIRSTPRIV+30) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, int cmd) +#else +static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, void __user *data, int cmd) +#endif { int ret = 0; ///TODO: add ioctl command handler later @@ -2761,7 +1386,11 @@ static int rwnx_set_mac_address(struct net_device *dev, void *addr) static const struct net_device_ops rwnx_netdev_ops = { .ndo_open = rwnx_open, .ndo_stop = rwnx_close, - .ndo_do_ioctl = rwnx_do_ioctl, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) + .ndo_do_ioctl = rwnx_do_ioctl, +#else + .ndo_siocdevprivate = rwnx_do_ioctl, +#endif .ndo_start_xmit = rwnx_start_xmit, .ndo_get_stats = rwnx_get_stats, #ifndef CONFIG_ONE_TXQ @@ -3826,6 +2455,7 @@ static int rwnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, { struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); struct rwnx_vif *rwnx_vif = netdev_priv(dev); + int ret = 0; RWNX_DBG(RWNX_FN_ENTRY_STR); @@ -3853,11 +2483,18 @@ static int rwnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, return -EBUSY; } - if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTED){ + if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTED) { atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); key_flag = true; - return(rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code)); - }else{ + ret = rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code); +#ifdef AICWF_SDIO_SUPPORT + if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) { + AICWFDBG(LOGINFO, "%s bus is down %d\n", __func__, ret); + atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); + } +#endif + return ret; + } else { cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, reason_code?reason_code:WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC); atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); @@ -4146,13 +2783,11 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, struct aicwf_rx_priv *rx_priv; #endif - //RWNX_DBG(RWNX_FN_ENTRY_STR); - printk("%s: %pM\n", __func__, mac); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) if (params) mac = params->mac; #endif + printk("%s: %pM\n", __func__, mac); do { spin_lock_bh(&rwnx_hw->cb_lock); @@ -4599,6 +3234,7 @@ static int rwnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, #if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL) rwnx_vif->ap.aic_index = 0; #endif + rwnx_vif->ap.csa = NULL; sta = &rwnx_hw->sta_table[apm_start_cfm.bcmc_idx]; sta->valid = true; sta->aid = 0; @@ -4961,9 +3597,9 @@ static int rwnx_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device * * notification by calling cfg80211_ready_on_channel(). */ static int -rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, +rwnx_cfg80211_remain_on_channel_(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, - unsigned int duration, u64 *cookie) + unsigned int duration, u64 *cookie, bool mgmt_roc_flag) { struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); //struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev); @@ -5012,12 +3648,14 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, rwnx_hw->vif_table[add_if_cfm.inst_nbr] = rwnx_vif; spin_unlock_bh(&rwnx_hw->cb_lock); rwnx_hw->is_p2p_alive = 1; +#ifndef CONFIG_USE_P2P0 mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); +#endif } else { #ifndef CONFIG_USE_P2P0 - mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); - atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); + mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); + atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); #endif } } @@ -5034,7 +3672,7 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, roc_elem->wdev = wdev; roc_elem->chan = chan; roc_elem->duration = duration; - roc_elem->mgmt_roc = false; + roc_elem->mgmt_roc = mgmt_roc_flag; roc_elem->on_chan = false; /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */ @@ -5065,6 +3703,15 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, return error; } + +static int +rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + return rwnx_cfg80211_remain_on_channel_(wiphy, wdev, chan, duration, cookie, false); +} + /** * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. * This allows the operation to be terminated prior to timeout based on @@ -5283,15 +3930,15 @@ static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, printk("mgmt rx remain on chan\n"); /* Start a ROC procedure for 30ms */ - error = rwnx_cfg80211_remain_on_channel(wiphy, wdev, channel, - 30, &cookie); + error = rwnx_cfg80211_remain_on_channel_(wiphy, wdev, channel, + 30, &cookie, true); if (error) { printk("mgmt rx chan err\n"); return error; } /* Need to keep in mind that RoC has been launched internally in order to * avoid to call the cfg80211 callback once expired */ - rwnx_hw->roc_elem->mgmt_roc = true; + //rwnx_hw->roc_elem->mgmt_roc = true; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) @@ -5441,11 +4088,6 @@ int rwnx_cfg80211_channel_switch (struct wiphy *wiphy, goto end; } - error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn_after->len); - if (error) { - goto end; - } - vif->ap.csa = csa; csa->vif = vif; csa->chandef = params->chandef; @@ -5737,14 +4379,19 @@ static int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif, sinfo->tx_failed = cfm.txfailed; rate_info = (union rwnx_rate_ctrl_info *)&cfm.rate_info; - AICWFDBG(LOGDEBUG, "%s ModTx:%d TxIndex:%d ModRx:%d RxHTIndex:%d RxVHTIndex:%d RxHEIndex:%d RSSI:%d \r\n", __func__, - rate_info->formatModTx, rate_info->mcsIndexTx, rx_vect1->format_mod, + AICWFDBG(LOGDEBUG, "%s ModTx(%d):%d TxIndex:%d ModRx(%d):%d RxHTIndex:%d RxVHTIndex:%d RxHEIndex:%d RSSI:%d \r\n", __func__, + rate_info->bwTx, + rate_info->formatModTx, + rate_info->mcsIndexTx, + rx_vect1->ch_bw, + rx_vect1->format_mod, rx_vect1->ht.mcs, rx_vect1->vht.mcs, rx_vect1->he.mcs, (s8)cfm.rssi); + switch (rate_info->formatModTx) { case FORMATMOD_NON_HT: case FORMATMOD_NON_HT_DUP_OFDM: @@ -7067,6 +5714,11 @@ int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) //wiphy_info(wiphy, "New interface create %s", vif->ndev->name); AICWFDBG(LOGINFO, "New interface create %s \r\n", vif->ndev->name); +#ifdef CONFIG_SDIO_BT + btchr_init(); + hdev_init(); +#endif + #ifdef CONFIG_USE_P2P0 rtnl_lock(); @@ -7152,6 +5804,12 @@ void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw) #ifdef CONFIG_DEBUG_FS rwnx_dbgfs_unregister(rwnx_hw); #endif + +#ifdef CONFIG_SDIO_BT + btchr_exit(); + hdev_exit(); +#endif + flush_workqueue(rwnx_hw->apmStaloss_wq); destroy_workqueue(rwnx_hw->apmStaloss_wq); @@ -7206,14 +5864,14 @@ static int __init rwnx_mod_init(void) rwnx_print_version(); rwnx_init_cmd_array(); -#ifndef CONFIG_PLATFORM_ROCKCHIP +//#ifndef CONFIG_PLATFORM_ROCKCHIP if (aicbsp_set_subsys(AIC_WIFI, AIC_PWR_ON) < 0) { AICWFDBG(LOGERROR, "%s, set power on fail!\n", __func__); if(!aicbsp_get_load_fw_in_fdrv()){ return -ENODEV; } } -#endif +//#endif init_completion(&hostif_register_done); aicsmac_driver_register(); diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.h index 684ab081f..dfa890347 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_main.h @@ -13,20 +13,6 @@ #include "rwnx_defs.h" -typedef struct _android_wifi_priv_cmd { - char *buf; - int used_len; - int total_len; -} android_wifi_priv_cmd; - -#ifdef CONFIG_COMPAT -typedef struct _compat_android_wifi_priv_cmd { - compat_caddr_t buf; - int used_len; - int total_len; -} compat_android_wifi_priv_cmd; -#endif /* CONFIG_COMPAT */ - int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data); void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw); extern int testmode; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_mod_params.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_mod_params.c index 4aa6eba9c..1fdced3ef 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_mod_params.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_mod_params.c @@ -269,6 +269,7 @@ static const int mcs_map_to_rate[4][3] = { #define MAX_VHT_RATE(map, nss, bw) (mcs_map_to_rate[bw][map] * (nss)) extern struct ieee80211_regdomain *reg_regdb[]; +extern int reg_regdb_size; char ccode_channels[200]; int index_for_channel_list = 0; @@ -891,6 +892,7 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) rwnx_hw->vht_cap_5G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80; } + rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; } #endif//USE_5G return; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_rx.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_rx.c index 662fb9378..c6e76b8a9 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_rx.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_rx.c @@ -25,6 +25,9 @@ #include "rwnx_compat.h" #include "aicwf_txrxif.h" #include "rwnx_msg_rx.h" +#ifdef CONFIG_SDIO_BT +#include "aic_btsdio.h" +#endif void rwnx_cfg80211_unlink_bss(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif); static int rwnx_freq_to_idx(struct rwnx_hw *rwnx_hw, int freq) @@ -275,6 +278,7 @@ found_vif: if (ps_state == MM_PS_MODE_OFF) { // Start TX queues for provided VIF rwnx_txq_vif_start(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); + tasklet_schedule(&rwnx_hw->task); } else { // Stop TX queues for provided VIF rwnx_txq_vif_stop(vif_entry, RWNX_TXQ_STOP_VIF_PS, rwnx_hw); @@ -383,6 +387,18 @@ static inline int rwnx_apm_staloss_ind(struct rwnx_hw *rwnx_hw, return 0; } +#ifdef CONFIG_SDIO_BT +static inline int rwnx_bt_recv_ind(struct rwnx_hw *rwnx_hw, + struct rwnx_cmd *cmd, + struct ipc_e2a_msg *msg) +{ + struct mm_bt_recv_ind *ind = (struct mm_bt_recv_ind *)msg->param; + + bt_sdio_recv(ind->bt_data,ind->data_len); + return 0; +} +#endif + static inline int rwnx_rx_csa_counter_ind(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, struct ipc_e2a_msg *msg) @@ -1481,6 +1497,9 @@ static msg_cb_fct tdls_hdlrs[MSG_I(TDLS_MAX)] = { [MSG_I(TDLS_CHAN_SWITCH_IND)] = rwnx_rx_tdls_chan_switch_ind, [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = rwnx_rx_tdls_chan_switch_base_ind, [MSG_I(TDLS_PEER_PS_IND)] = rwnx_rx_tdls_peer_ps_ind, +#ifdef CONFIG_SDIO_BT + [MSG_I(TDLS_SDIO_BT_RECV_IND)] = rwnx_bt_recv_ind, +#endif }; static msg_cb_fct *msg_hdlrs[] = { @@ -1501,7 +1520,7 @@ static msg_cb_fct *msg_hdlrs[] = { */ void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg) { - //printk("%s msg->id:0x%x \r\n", __func__, msg->id); + AICWFDBG(LOGDEBUG, "%s msg->id:0x%x \r\n", __func__, msg->id); rwnx_hw->cmd_mgr->msgind(rwnx_hw->cmd_mgr, msg, msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.c index 054afeb7a..f62475b4e 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.c @@ -942,6 +942,31 @@ int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_v } #endif +int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx) +{ + struct mm_set_agg_disable_req *req; + int error; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + /* Build the MM_SET_AGG_DISABLE_REQ message */ + req = rwnx_msg_zalloc(MM_SET_AGG_DISABLE_REQ, TASK_MM, DRV_TASK_ID, + sizeof(struct mm_set_agg_disable_req)); + + if (!req) { + return -ENOMEM; + } + + req->disable = agg_disable; + req->staidx = sta_idx; + req->disable_rx = agg_disable_rx; + + /* Send the MM_SET_AGG_DISABLE_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_AGG_DISABLE_CFM, NULL); + + return (error); +}; + int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts) { struct mm_set_coex_req *coex_req; @@ -1149,8 +1174,11 @@ int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, struct mm_set_mac_timescale_req *req2; struct mm_set_cca_threshold_req *req3; struct mm_set_bwmode_req *req4; + struct mm_set_ap_ps_level_req *req5 = NULL; + struct mm_set_customized_freq_req *req6; int error = 0; + int i; switch (hwconfig_id) { @@ -1240,29 +1268,68 @@ int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ error = rwnx_send_msg(rwnx_hw, req4, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); break; - case CHIP_TEMP_GET_REQ: - if ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || - (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) - { - struct mm_get_chip_temp_req *req; - struct mm_set_vendor_hwconfig_cfm cfm = {0,}; - /* Build the CHIP_TEMP_GET_REQ message */ - req = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_chip_temp_req)); - if (!req) - return -ENOMEM; - req->hwconfig_id = hwconfig_id; - /* Send the MM_SET_VENDOR_HWCONFIG_REQ message to UMAC FW */ - error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_HWCONFIG_CFM, &cfm); - if (!error) { - if (param_out) { - param_out[0] = (int32_t)cfm.chip_temp_cfm.degree; + case CHIP_TEMP_GET_REQ: + if ((rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || + (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) + { + struct mm_get_chip_temp_req *req; + struct mm_set_vendor_hwconfig_cfm cfm = {0,}; + /* Build the CHIP_TEMP_GET_REQ message */ + req = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_get_chip_temp_req)); + if (!req) + return -ENOMEM; + req->hwconfig_id = hwconfig_id; + /* Send the MM_SET_VENDOR_HWCONFIG_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_HWCONFIG_CFM, &cfm); + if (!error) { + if (param_out) { + param_out[0] = (int32_t)cfm.chip_temp_cfm.degree; + } + printk("get_chip_temp degree=%d\n", cfm.chip_temp_cfm.degree); + } else { + printk("get_chip_temp err=%d\n", error); + } } - printk("get_chip_temp degree=%d\n", cfm.chip_temp_cfm.degree); - } else { - printk("get_chip_temp err=%d\n", error); - } - } - break; + break; + case AP_PS_LEVEL_SET_REQ: + /* + AP_PS_CLK_1 = 1, // 3:7 -> active 3, doze 7 + AP_PS_CLK_2, // 5:5 -> active 5, doze 5 + AP_PS_CLK_3, // 7:3 -> active 7, doze 3 + AP_PS_CLK_4, // 8:2 -> active 8, doze 2 + AP_PS_CLK_5, // 9:1 -> active 9, doze 1 + */ + /* Build the MM_SET_VENDOR_HWCONFIG_REQ message */ + req5 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, + sizeof(struct mm_set_ap_ps_level_req)); + if (!req5) { + return -ENOMEM; + } + req5->hwconfig_id = hwconfig_id; + req5->ap_ps_level = param[0]; + + /* Send the MM_GET_MAC_ADDR_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); + if(!error) + printk("set ap_ps_level=%d \n",param[0]); + break; + + case CUSTOMIZED_FREQ_REQ: + /* Build the CUSTOMIZED_FREQ_REQ message */ + req6 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_customized_freq_req)); + if (!req6) + return -ENOMEM; + req5->hwconfig_id = hwconfig_id; + for (i = 0; i < 4; i++) { + req6->raw_freq[i] = param [i]; + req6->map_freq[i] = param [i + 4]; + } + printk("customized_freq_req: raw_freq[ %d %d %d %d ], map_freq[ %d %d %d %d]\n", + param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]); + /* Send the MM_SET_VENDOR_HWCONFIG_CFM message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req5, 1, MM_SET_VENDOR_HWCONFIG_CFM, NULL); + + break; default: return -ENOMEM; } @@ -1321,6 +1388,44 @@ int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, } break; + case EXT_FLAGS_SET_REQ: + /* Build the EXT_FLAGS_SET_REQ message */ + req->ext_flags_set_req.user_flags = (u32_l)param_in[0]; + printk("ext_flags_set_req: flags=%x\n", + req->ext_flags_set_req.user_flags); + /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); + if (!error) { + param_out[0] = (uint32_t)cfm.ext_flags_set_cfm.user_flags; + printk("cfm flags=%x\n", cfm.ext_flags_set_cfm.user_flags); + } + break; + + case EXT_FLAGS_GET_REQ: + /* Build the EXT_FLAGS_GET_REQ message */ + printk("ext_flags_get_req\n"); + /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); + if (!error) { + param_out[0] = (uint32_t)cfm.ext_flags_get_cfm.user_flags; + printk("cfm flags=%x\n", cfm.ext_flags_get_cfm.user_flags); + } + break; + + case EXT_FLAGS_MASK_SET_REQ: + /* Build the EXT_FLAGS_MASK_SET_REQ message */ + req->ext_flags_mask_set_req.user_flags_mask = (u32_l)param_in[0]; + req->ext_flags_mask_set_req.user_flags_val = (u32_l)param_in[1]; + printk("ext_flags_mask_set_req: flags mask=0x%x, val=0x%x\n", + req->ext_flags_mask_set_req.user_flags_mask, req->ext_flags_mask_set_req.user_flags_val); + /* Send the MM_SET_VENDOR_SWCONFIG_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, &cfm); + if (!error) { + param_out[0] = (uint32_t)cfm.ext_flags_mask_set_cfm.user_flags; + printk("cfm flags=%x\n", cfm.ext_flags_mask_set_cfm.user_flags); + } + break; + default: error = -ENOMEM; break; @@ -1329,6 +1434,57 @@ int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, return error; } +int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm) +{ + struct mm_set_vendor_swconfig_req *req; + int ret; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + /* Build the REQ message */ + req = rwnx_msg_zalloc(MM_SET_VENDOR_SWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_vendor_swconfig_req)); + if (!req) { + AICWFDBG(LOGERROR, "%s msg_alloc fail\n", __func__); + return -ENOMEM; + } + req->swconfig_id = EXT_FLAGS_MASK_SET_REQ; + req->ext_flags_mask_set_req.user_flags_mask = (u32_l)flags_mask; + req->ext_flags_mask_set_req.user_flags_val = (u32_l)flags_val; + + ret = rwnx_send_msg(rwnx_hw, req, 1, MM_SET_VENDOR_SWCONFIG_CFM, cfm); + if (!ret) { + AICWFDBG(LOGINFO, "curr ext_flags=%x\n", cfm->ext_flags_mask_set_cfm.user_flags); + } else { + AICWFDBG(LOGERROR, "%s send_msg_fail\n", __func__); + return ret; + } + return ret; +} + +#ifdef CONFIG_SDIO_BT +int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb) +{ + struct mm_bt_send_req *req; + struct mm_bt_send_cfm cfm; + int error; + + cfm.status = 0; + req = rwnx_msg_zalloc(TDLS_SDIO_BT_SEND_REQ, TASK_TDLS, DRV_TASK_ID, sizeof(struct mm_bt_send_req)); + + if (!req) { + return -ENOMEM; + } + + req->data_len = len; + memcpy(req->bt_data,skb->data,len); + + error = rwnx_send_msg(rwnx_hw, req, 1, TDLS_SDIO_BT_SEND_CFM, &cfm); + if(!cfm.status){ + printk("bt send no cfm"); + } + + return error; +} +#endif int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm) { @@ -1560,6 +1716,52 @@ int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw) } } +int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw) +{ + struct mm_set_txpwr_lvl_adj_req *txpwr_lvl_adj_req; + txpwr_lvl_adj_conf_t txpwr_lvl_adj_tmp; + txpwr_lvl_adj_conf_t *txpwr_lvl_adj; + int error; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + /* Build the MM_SET_TXPWR_LVL_REQ message */ + txpwr_lvl_adj_req = rwnx_msg_zalloc(MM_SET_TXPWR_LVL_ADJ_REQ, TASK_MM, DRV_TASK_ID, + sizeof(struct mm_set_txpwr_lvl_adj_req)); + + if (!txpwr_lvl_adj_req) { + return -ENOMEM; + } + + txpwr_lvl_adj = &txpwr_lvl_adj_tmp; + + get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj); + + if (txpwr_lvl_adj->enable == 0) { + rwnx_msg_free(rwnx_hw, txpwr_lvl_adj_req); + return 0; + } else { + AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); + AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); + AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); + AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); + + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); + + txpwr_lvl_adj_req->txpwr_lvl_adj = *txpwr_lvl_adj; + + /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, txpwr_lvl_adj_req, 1, MM_SET_TXPWR_LVL_ADJ_CFM, NULL); + + return (error); + } +} + int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) { struct mm_set_txpwr_idx_req *txpwr_idx_req; @@ -1911,6 +2113,13 @@ int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened, u8 s return rwnx_send_msg(rwnx_hw, req, 1, ME_SET_CONTROL_PORT_CFM, NULL); } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)) +struct ieee80211_he_cap_elem_4_19 { + u8 mac_cap_info[6]; + u8 phy_cap_info[11]; +} __packed; +#endif + int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params, const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm) { @@ -1977,20 +2186,24 @@ int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *par } #elif defined(CONFIG_VHT_FOR_OLD_KERNEL) if (sta->vht) { - const struct ieee80211_vht_cap *vht_capa = rwnx_vht_capa; + //const struct ieee80211_vht_cap *vht_capa = rwnx_vht_capa; req->flags |= STA_VHT_CAPA; - req->vht_cap.vht_capa_info = cpu_to_le32(vht_capa->vht_cap_info); - req->vht_cap.rx_highest = cpu_to_le16(vht_capa->supp_mcs.rx_highest); - req->vht_cap.rx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.rx_mcs_map); - req->vht_cap.tx_highest = cpu_to_le16(vht_capa->supp_mcs.tx_highest); - req->vht_cap.tx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.tx_mcs_map); + req->vht_cap.vht_capa_info = cpu_to_le32(rwnx_vht_capa->cap); + req->vht_cap.rx_highest = cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_highest); + req->vht_cap.rx_mcs_map = cpu_to_le16(rwnx_vht_capa->vht_mcs.rx_mcs_map); + req->vht_cap.tx_highest = cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_highest); + req->vht_cap.tx_mcs_map = cpu_to_le16(rwnx_vht_capa->vht_mcs.tx_mcs_map); } #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) if (link_sta_params->he_capa) { + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) + const struct ieee80211_he_cap_elem_4_19 *he_capa = (const struct ieee80211_he_cap_elem_4_19 *) link_sta_params->he_capa; + #else const struct ieee80211_he_cap_elem *he_capa = link_sta_params->he_capa; + #endif struct ieee80211_he_mcs_nss_supp *mcs_nss_supp = (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1); @@ -2292,7 +2505,8 @@ int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw, rwnx_vif->sta.ssid_len = (int)sme->ssid_len; memset(rwnx_vif->sta.ssid, 0, rwnx_vif->sta.ssid_len + 1); memcpy(rwnx_vif->sta.ssid, sme->ssid, rwnx_vif->sta.ssid_len); - memcpy(rwnx_vif->sta.bssid, sme->bssid, ETH_ALEN); + if (sme->bssid) + memcpy(rwnx_vif->sta.bssid, sme->bssid, ETH_ALEN); printk("%s drv_vif_index:%d connect to %s(%d) channel:%d auth_type:%d\r\n", __func__, diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.h index a3890fe2b..836f43b91 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_msg_tx.h @@ -161,6 +161,7 @@ int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr, int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr, u32 boot_type); int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst); +int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx); int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts); int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm); int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info, @@ -169,12 +170,17 @@ int rwnx_send_txop_req(struct rwnx_hw *rwnx_hw, uint16_t *txop, u8_l long_nav_en int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm); int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out); int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out); +int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm); int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm); int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw); int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw); int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw); int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw); int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw); +int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw); +#ifdef CONFIG_SDIO_BT +int rwnx_sdio_bt_send_req(struct rwnx_hw *rwnx_hw,uint32_t len, struct sk_buff *skb); +#endif #endif /* _RWNX_MSG_TX_H_ */ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.c index 4ca92f8f3..b826b4b02 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.c @@ -55,6 +55,7 @@ typedef struct txpwr_lvl_conf_t txpwr_lvl; txpwr_lvl_conf_v2_t txpwr_lvl_v2; txpwr_lvl_conf_v3_t txpwr_lvl_v3; + txpwr_lvl_adj_conf_t txpwr_lvl_adj; txpwr_loss_conf_t txpwr_loss; txpwr_ofst_conf_t txpwr_ofst; txpwr_ofst2x_conf_t txpwr_ofst2x; @@ -629,6 +630,67 @@ void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap) AICWFDBG(LOGINFO, "%s:xtal_cap_fine:%d\r\n", __func__, xtal_cap->xtal_cap_fine); } +s8_l get_txpwr_max(s8_l power) +{ + int i=0; + + for (i = 0; i <= 11; i++){ + if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]) + power = userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i]; + } + for (i = 0; i <= 9; i++){ + if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]) + power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i]; + } + for (i = 0; i <= 11; i++){ + if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]) + power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i]; + } + for (i = 4; i <= 11; i++){ + if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]) + power = userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i]; + } + for (i = 0; i <= 9; i++){ + if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]) + power = userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i]; + } + for (i = 0; i <= 11; i++){ + if(power < userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]) + power = userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i]; + } + + if(userconfig_info.txpwr_loss.loss_enable == 1) + power += userconfig_info.txpwr_loss.loss_value; + + printk("%s:txpwr_max:%d \r\n",__func__,power); + return power; +} + +void set_txpwr_loss_ofst(s8_l value) +{ + int i=0; + + for (i = 0; i <= 11; i++){ + userconfig_info.txpwr_lvl_v3.pwrlvl_11b_11ag_2g4[i] += value; + } + for (i = 0; i <= 9; i++){ + userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_2g4[i] += value; + } + for (i = 0; i <= 11; i++){ + userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_2g4[i] += value; + } + for (i = 4; i <= 11; i++){ + userconfig_info.txpwr_lvl_v3.pwrlvl_11a_5g[i] += value; + } + for (i = 0; i <= 9; i++){ + userconfig_info.txpwr_lvl_v3.pwrlvl_11n_11ac_5g[i] += value; + } + for (i = 0; i <= 11; i++){ + userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[i] += value; + } + + printk("%s:value:%d\r\n", __func__, value); +} #define MATCH_NODE(type, node, cfg_key) {cfg_key, offsetof(type, node)} @@ -1040,6 +1102,26 @@ void rwnx_plat_nvram_set_value_v3(char *command, char *value) userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[10] = rwnx_atoi(value); } else if (!strcmp(command, "lvl_11ax_mcs11_5g")) { userconfig_info.txpwr_lvl_v3.pwrlvl_11ax_5g[11] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_enable")) { + userconfig_info.txpwr_lvl_adj.enable = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_2g4_chan_1_4")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[0] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_2g4_chan_5_9")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[1] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_2g4_chan_10_13")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_2g4[2] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_5g_chan_42")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_5g_chan_58")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_5g_chan_106")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_5g_chan_122")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_5g_chan_138")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); + } else if (!strcmp(command, "lvl_adj_5g_chan_155")) { + userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); } else if (!strcmp(command, "loss_enable")) { userconfig_info.txpwr_loss.loss_enable = rwnx_atoi(value); } else if (!strcmp(command, "loss_value")) { @@ -1875,6 +1957,23 @@ void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3) AICWFDBG(LOGINFO, "%s:lvl_11ax_mcs11_5g:%d\r\n", __func__, txpwr_lvl_v3->pwrlvl_11ax_5g[11]); } +void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj) +{ + *txpwr_lvl_adj = userconfig_info.txpwr_lvl_adj; + + AICWFDBG(LOGINFO, "%s:enable:%d\r\n", __func__, txpwr_lvl_adj->enable); + AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_1_4:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[0]); + AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_5_9:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[1]); + AICWFDBG(LOGINFO, "%s:lvl_adj_2g4_chan_10_13:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_2g4[2]); + + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_42:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[0]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_58:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[1]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_106:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[2]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_122:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[3]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_138:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[4]); + AICWFDBG(LOGINFO, "%s:lvl_adj_5g_chan_155:%d\r\n", __func__, txpwr_lvl_adj->pwrlvl_adj_tbl_5g[5]); +} + /** * rwnx_plat_userconfig_load ---Load aic_userconfig.txt *@filename name of config diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.h index 925061234..32d88e188 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_platform.h @@ -117,10 +117,13 @@ void rwnx_platform_unregister_drv(void); void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx); void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst); void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap); +s8_l get_txpwr_max(s8_l power); +void set_txpwr_loss_ofst(s8_l value); void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl); void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2); void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3); +void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj); void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst); void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x); diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_rx.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_rx.c index 02641e41b..d740f146a 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_rx.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_rx.c @@ -681,6 +681,9 @@ static void rwnx_rx_mgmt(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, const u8* ie; u32 len; + if(skb->data[0]!=0x80) + AICWFDBG(LOGDEBUG,"rxmgmt:%x,%x\n", skb->data[0], skb->data[1]); + if (ieee80211_is_assoc_req(mgmt->frame_control) && rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) { printk("ASSOC_REQ: sta_idx %d MAC %pM\n", rwnx_vif->ap.aic_index, mgmt->sa); sta->sta_idx = rwnx_vif->ap.aic_index; @@ -1771,7 +1774,7 @@ int reord_process_unit(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u16 s spin_lock_bh(&preorder_ctrl->reord_list_lock); if (reord_need_check(preorder_ctrl, pframe->seq_num)) { -#if 0 +#if 1 if(pframe->rx_data[42] == 0x80){//this is rtp package if(pframe->seq_num == preorder_ctrl->ind_sn){ printk("%s pframe->seq_num1:%d \r\n", __func__, pframe->seq_num); @@ -1943,7 +1946,7 @@ void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 } //printk("sublen = %d, %x, %x, %x, %x\r\n", sublen,skb->data[0], skb->data[1], skb->data[12], skb->data[13]); #if 1 - sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_KERNEL); + sub_skb = __dev_alloc_skb(sublen - 6 + 12, GFP_ATOMIC); if(!sub_skb){ printk("sub_skb alloc fail:%d\n", sublen); break; diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_tx.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_tx.c index 7be91e061..dc9d2ccd5 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_tx.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_tx.c @@ -169,7 +169,7 @@ void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, // sta->mac_addr)) // return; if (!sta->ps.active) { - printk("sta %pM is not in Power Save mode", sta->mac_addr); + AICWFDBG(LOGTRACE,"sta %pM is not in Power Save mode", sta->mac_addr); return; } #ifdef CREATE_TRACE_POINTS @@ -641,7 +641,10 @@ void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags) sw_txhdr->need_cfm = 1; sw_txhdr->desc.host.hostid = ((1<<31) | rwnx_hw->sdio_env.txdesc_free_idx[0]); aicwf_sdio_host_txdesc_push(&(rwnx_hw->sdio_env), 0, (long)skb); - AICWFDBG(LOGINFO, "need cfm ethertype:%8x,user_idx=%d, skb=%p\n", sw_txhdr->desc.host.ethertype, rwnx_hw->sdio_env.txdesc_free_idx[0], skb); + if((sw_txhdr->desc.host.flags & TXU_CNTRL_MGMT)) + AICWFDBG(LOGINFO, "need cfm mgmt:%x,user_idx=%d, skb=%p\n", *(skb->data+sw_txhdr->headroom), rwnx_hw->sdio_env.txdesc_free_idx[0], skb); + else + AICWFDBG(LOGINFO, "need cfm ethertype:%8x,user_idx=%d, skb=%p\n", sw_txhdr->desc.host.ethertype, rwnx_hw->sdio_env.txdesc_free_idx[0], skb); } else { sw_txhdr->need_cfm = 0; sw_txhdr->desc.host.hostid = 0; @@ -1418,6 +1421,9 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev) skb = newskb; } + if(skb->priority < 3) + skb->priority = 0; + #ifdef CONFIG_FILTER_TCP_ACK msgbuf=intf_tcp_alloc_msg(msgbuf); msgbuf->rwnx_vif=rwnx_vif; @@ -1615,6 +1621,8 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, bool no_cck = params->no_cck; #endif + AICWFDBG(LOGDEBUG,"mgmt xmit %x %x ",buf[0],buf[1]); + if((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8801) || ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC || g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_txq.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_txq.c index a776e31e9..5468c3a5e 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_txq.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_txq.c @@ -19,6 +19,11 @@ #ifdef CONFIG_RWNX_FULLMAC const int nx_tid_prio[NX_NB_TID_PER_STA] = {7, 6, 5, 4, 3, 0, 2, 1}; +#ifdef CONFIG_TX_NETIF_FLOWCTRL +extern int tx_fc_low_water; +extern int tx_fc_high_water; +#endif + static inline int rwnx_txq_sta_idx(struct rwnx_sta *sta, u8 tid) { if (is_multicast_sta(sta->sta_idx)){ @@ -853,9 +858,17 @@ int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, /* Flowctrl corresponding netdev queue if needed */ #ifdef CONFIG_RWNX_FULLMAC #ifndef CONFIG_ONE_TXQ + +#ifdef CONFIG_TX_NETIF_FLOWCTRL + if ((txq->ndev_idx != NDEV_NO_TXQ) && ((skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP) && + !rwnx_hw->sdiodev->flowctrl)) { +// (atomic_read(&rwnx_hw->sdiodev->tx_priv->tx_pktcnt) >= tx_fc_high_water))) { +#else /* If too many buffer are queued for this TXQ stop netdev queue */ if ((txq->ndev_idx != NDEV_NO_TXQ) && (skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP)) { +#endif + txq->status |= RWNX_TXQ_NDEV_FLOW_CTRL; netif_stop_subqueue(txq->ndev, txq->ndev_idx); #ifdef CREATE_TRACE_POINT @@ -1292,8 +1305,14 @@ void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) } #ifndef CONFIG_ONE_TXQ /* restart netdev queue if number of queued buffer is below threshold */ +#ifdef CONFIG_TX_NETIF_FLOWCTRL + if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && + (skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART)) { +#else if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART) { +#endif + txq->status &= ~RWNX_TXQ_NDEV_FLOW_CTRL; netif_wake_subqueue(txq->ndev, txq->ndev_idx); #ifdef CREATE_TRACE_POINTS diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_version_gen.h b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_version_gen.h index 5185e9229..6ce7186ae 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_version_gen.h +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_version_gen.h @@ -1,4 +1,4 @@ #define RWNX_VERS_REV "241c091M (master)" #define RWNX_VERS_MOD "6.4.3.0" #define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" -#define RELEASE_DATE "2023_1219_3cf85031" +#define RELEASE_DATE "2024_0615_c3cb37b3" diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_wakelock.c b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_wakelock.c index 69bcf3f5d..1d1529627 100755 --- a/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_wakelock.c +++ b/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/rwnx_wakelock.c @@ -82,5 +82,9 @@ void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw) rwnx_wakeup_deinit(rwnx_hw->ws_rx); rwnx_wakeup_deinit(rwnx_hw->ws_irqrx); rwnx_wakeup_deinit(rwnx_hw->ws_pwrctrl); + rwnx_hw->ws_tx = NULL; + rwnx_hw->ws_rx = NULL; + rwnx_hw->ws_irqrx = NULL; + rwnx_hw->ws_pwrctrl = NULL; } diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin index 59604d328..c395f04b2 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_hbt_u02.bin similarity index 61% rename from sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin rename to sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_hbt_u02.bin index 59604d328..4eaed180f 100755 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_calib_8800dc_h_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_hbt_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin index bc175da27..85dd6c952 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin index 7615a823d..cea05b9e9 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_hbt_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_hbt_u02.bin new file mode 100755 index 000000000..ff16e4b16 Binary files /dev/null and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_hbt_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin index fa8edfb58..ca9a0b0f4 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin index 899571a25..72cdf58db 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_hbt_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_hbt_u02.bin new file mode 100755 index 000000000..0f0bee235 Binary files /dev/null and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_hbt_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin index 4d6285ac3..9d7fb2415 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02.bin index 220c6a894..7e59a4e35 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02h.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02h.bin index 30053f00b..4bc2f2b74 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02h.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_8800dc_u02h.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02.bin index 7555f5d4a..6a6b5d3a9 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin index 1cb983077..bead5ff71 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin differ diff --git a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/lmacfw_rf_8800dc.bin b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/lmacfw_rf_8800dc.bin index d0f3215d2..1f5ba9b51 100755 Binary files a/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/lmacfw_rf_8800dc.bin and b/sysdrv/drv_ko/wifi/aic8800dc/aic8800dc_fw/lmacfw_rf_8800dc.bin differ diff --git a/sysdrv/source/kernel/arch/arm/boot/dts/rv1106-luckfox-pico-ultra-ipc.dtsi b/sysdrv/source/kernel/arch/arm/boot/dts/rv1106-luckfox-pico-ultra-ipc.dtsi index 20dcfd812..0874d4bb2 100755 --- a/sysdrv/source/kernel/arch/arm/boot/dts/rv1106-luckfox-pico-ultra-ipc.dtsi +++ b/sysdrv/source/kernel/arch/arm/boot/dts/rv1106-luckfox-pico-ultra-ipc.dtsi @@ -81,7 +81,7 @@ hsync-active = <0>; vsync-active = <0>; de-active = <0>; - pixelclk-active = <1>; + pixelclk-active = <0>; }; }; diff --git a/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-luckfox-pico-ultra-w.dts b/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-luckfox-pico-ultra-w.dts index 879beb112..4bf986d6c 100755 --- a/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-luckfox-pico-ultra-w.dts +++ b/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-luckfox-pico-ultra-w.dts @@ -24,6 +24,17 @@ reset-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; }; + wireless_bluetooth: wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts_gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart1m0_rtsn>; + pinctrl-1 = <&uart1_gpios>; + BT,wake_gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + BT,wake_host_irq = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + }; /**********EMMC**********/ @@ -95,16 +106,13 @@ &uart1 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>; + pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn>; }; &pinctrl { - uart1 { - uart1m0_ctsn: uart1m0-ctsn{ - rockchip,pins = <0 RK_PA6 2 &pcfg_pull_down>; - }; - uart1m0_rtsn: uart1m0-rtsn{ - rockchip,pins = <0 RK_PA5 2 &pcfg_pull_down>; + wireless-bluetooth { + uart1_gpios: uart1-gpios { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; }; }; }; diff --git a/sysdrv/source/kernel/drivers/video/logo/logo_linux_clut224.ppm b/sysdrv/source/kernel/drivers/video/logo/logo_linux_clut224.ppm index 4d1c40a81..3686a4259 100644 --- a/sysdrv/source/kernel/drivers/video/logo/logo_linux_clut224.ppm +++ b/sysdrv/source/kernel/drivers/video/logo/logo_linux_clut224.ppm @@ -506,10 +506,14 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +8 3 0 98 43 0 159 68 0 183 82 0 173 76 0 128 54 0 +75 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 21 0 +110 51 0 159 68 0 183 82 0 173 76 0 128 54 0 48 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -551,18 +555,20 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 27 0 +207 91 0 235 98 0 235 98 0 235 98 0 235 98 0 235 98 0 +235 98 0 183 82 0 61 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 21 23 27 -14 22 27 9 20 28 9 20 28 14 22 27 18 24 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 8 0 128 54 0 235 98 0 +235 98 0 235 98 0 235 98 0 235 98 0 235 98 0 235 98 0 +118 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 27 18 24 27 14 22 27 9 20 28 -9 20 28 14 22 27 21 23 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -599,20 +605,21 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 48 22 0 235 100 0 +235 100 0 235 100 0 235 100 0 235 100 0 235 100 0 235 100 0 +235 100 0 235 100 0 235 100 0 118 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 65 29 0 207 91 0 235 100 0 235 100 0 +235 100 0 235 100 0 235 100 0 235 100 0 235 100 0 235 100 0 +235 100 0 138 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 22 25 27 14 22 27 35 31 25 -85 50 19 111 56 15 148 72 11 85 50 19 43 33 24 14 22 27 -18 24 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 27 17 22 27 14 22 27 57 39 22 111 56 15 111 56 15 -111 56 15 85 50 19 35 31 25 14 22 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -648,21 +655,21 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 220 97 0 236 102 0 +236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 +236 102 0 236 102 0 236 102 0 236 101 0 183 82 0 36 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 118 52 0 236 101 0 236 102 0 236 102 0 236 102 0 +236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 +236 102 0 236 101 0 61 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 22 25 27 14 20 27 111 56 15 196 92 5 -249 107 0 236 99 0 236 99 0 236 99 0 223 98 1 148 72 11 -43 33 24 14 22 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -16 21 27 57 39 22 148 72 11 223 98 1 236 99 0 241 105 0 -249 107 0 236 99 0 196 92 5 85 50 19 14 22 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -698,22 +705,23 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 98 43 0 236 102 0 236 102 0 +236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 +236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 235 101 0 +86 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 16 0 +183 82 0 236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 +236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 236 102 0 +236 102 0 236 102 0 190 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 27 4 17 28 148 72 11 236 99 0 241 105 0 -236 99 0 236 99 0 236 99 0 236 99 0 236 99 0 249 107 0 -223 98 1 85 50 19 10 17 28 18 24 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 18 24 27 4 17 28 -111 56 15 223 98 1 249 107 0 236 99 0 236 99 0 236 99 0 -236 99 0 236 99 0 249 107 0 236 99 0 111 56 15 4 17 28 -23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -747,23 +755,24 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 190 88 0 236 104 0 236 104 0 +236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 +236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 +236 104 0 147 68 0 8 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 83 40 0 235 101 0 +236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 +236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 236 104 0 +236 104 0 236 104 0 236 104 0 48 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 27 14 22 27 85 50 19 249 107 0 236 99 0 236 99 0 -236 99 0 236 99 0 236 99 0 236 100 0 236 99 0 236 99 0 -236 99 0 249 107 0 173 86 8 21 23 27 14 22 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 27 22 25 27 14 22 27 35 31 25 173 86 8 -249 107 0 241 105 0 236 99 0 236 99 0 236 99 0 236 99 0 -236 99 0 236 99 0 236 99 0 236 99 0 249 107 0 69 44 21 -14 22 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -796,24 +805,24 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 13 8 0 236 104 0 236 105 1 236 105 1 +236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 +236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 +236 105 1 236 105 1 207 91 0 61 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 8 5 0 138 64 0 236 105 1 236 105 1 +236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 +236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 236 105 1 +236 105 1 236 105 1 236 105 1 110 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -21 23 27 29 29 28 196 92 5 241 105 0 236 100 0 236 101 0 -236 101 0 236 101 0 236 101 0 236 101 0 236 101 0 236 101 0 -236 100 0 236 99 0 249 107 0 196 92 5 57 39 22 18 22 27 -22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 27 22 25 27 13 20 27 85 50 19 223 98 1 236 99 0 -236 100 0 236 100 0 236 101 0 236 101 0 236 101 0 236 101 0 -236 101 0 236 101 0 236 100 0 236 100 0 241 105 0 196 92 5 -9 20 28 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -846,174 +855,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -13 20 27 85 50 19 241 105 0 241 105 0 236 103 0 236 103 0 -236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 -236 103 0 236 103 0 236 99 0 241 105 0 236 100 0 111 56 15 -9 20 28 17 22 27 23 25 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -14 22 27 23 25 27 111 56 15 236 101 0 241 105 0 236 101 0 -236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 -236 103 0 236 103 0 236 103 0 236 103 0 236 99 0 249 107 0 -43 33 24 18 24 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -9 20 28 148 72 11 241 105 0 236 103 0 236 103 0 236 103 0 -236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 -236 103 0 236 103 0 236 103 0 236 103 0 238 106 0 249 114 0 -173 86 8 57 39 22 13 20 27 22 25 27 23 25 27 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 22 25 27 9 20 28 -69 44 21 196 92 5 249 114 0 241 105 0 238 106 0 236 103 0 -238 106 0 236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 -236 103 0 236 103 0 236 103 0 236 103 0 236 103 0 249 107 0 -111 56 15 17 22 27 23 25 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -18 24 27 173 86 8 249 107 0 235 106 1 235 106 1 235 106 1 -235 106 1 235 106 1 235 106 1 235 106 1 235 106 1 235 106 1 -235 106 1 235 106 1 235 106 1 235 106 1 236 106 0 238 106 0 -241 105 0 223 98 1 85 50 19 14 22 27 21 23 27 23 25 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 27 18 24 27 18 24 27 111 56 15 -223 98 1 241 105 0 238 106 0 236 106 0 235 106 1 235 106 1 -235 106 1 235 106 1 235 106 1 235 106 1 235 106 1 235 106 1 -235 106 1 235 106 1 235 106 1 235 106 1 235 106 1 249 114 0 -148 72 11 17 22 27 23 25 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -26 27 26 173 86 8 249 114 0 235 106 1 236 107 1 236 107 1 +0 0 0 0 0 0 48 22 0 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 -237 108 0 237 109 1 241 105 0 148 72 11 14 22 27 14 22 27 -23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 27 13 20 27 23 25 27 148 72 11 240 113 0 -241 105 0 237 110 0 236 107 1 236 107 1 236 107 1 236 107 1 +236 107 1 236 107 1 236 107 1 236 107 1 118 52 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 57 27 0 207 91 0 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 -236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 249 114 0 -173 86 8 17 22 27 22 25 27 0 0 0 0 0 0 0 0 0 +236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 236 107 1 +236 107 1 236 107 1 236 107 1 138 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1053,19 +904,17 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 27 -35 31 25 196 92 5 240 113 0 237 109 1 237 109 1 237 109 1 -237 109 1 237 109 1 237 109 1 237 109 1 240 113 0 237 109 1 -237 109 1 237 109 1 237 109 1 237 109 1 237 109 1 237 109 1 -237 109 1 237 109 1 240 113 0 249 114 0 196 92 5 69 44 21 -9 20 28 22 25 27 23 25 27 0 0 0 0 0 0 23 25 27 -21 23 27 9 20 28 69 44 21 235 106 1 249 114 0 240 113 0 -237 111 1 237 109 1 237 109 1 237 109 1 237 109 1 237 109 1 -237 109 1 237 109 1 237 109 1 240 113 0 237 110 0 237 109 1 -237 109 1 237 109 1 237 109 1 237 109 1 237 111 1 241 105 0 -173 86 8 24 26 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 65 29 0 237 108 1 237 108 1 237 108 1 +237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 +237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 +237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 183 82 0 +31 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +118 52 0 237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 +237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 +237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 237 108 1 +237 108 1 237 108 1 237 108 1 159 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1103,20 +952,19 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -26 27 26 196 92 5 240 113 0 237 111 1 237 111 1 237 111 1 -237 111 1 237 111 1 240 113 0 223 98 1 223 98 1 240 113 0 -237 110 0 237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 -237 111 1 237 111 1 237 111 1 237 110 0 249 114 0 240 113 0 -111 56 15 14 22 27 18 23 27 23 25 27 23 25 27 18 23 27 -21 23 27 119 81 15 249 107 0 240 113 0 237 110 0 237 109 1 -237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 -237 111 1 237 110 0 249 114 0 223 98 1 223 98 1 237 112 0 -237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 249 114 0 -173 86 8 21 24 26 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 75 35 0 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 109 1 +227 107 1 83 40 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 26 13 0 183 82 0 +237 109 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 158 78 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1153,21 +1001,20 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -26 27 26 173 86 8 240 113 0 237 111 1 237 111 1 237 111 1 -237 111 1 237 111 1 240 113 0 173 86 8 57 39 22 196 92 5 -249 114 0 240 113 0 237 111 1 237 111 1 237 111 1 237 111 1 -237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 240 113 0 -247 119 0 173 86 8 29 29 28 9 20 28 9 20 28 35 31 25 -196 92 5 249 114 0 240 113 0 237 111 1 237 111 1 237 111 1 -237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 237 111 1 -240 113 0 247 119 0 196 92 5 18 24 27 196 92 5 240 113 0 -237 111 1 237 111 1 237 111 1 237 111 1 236 112 1 249 114 0 -148 72 11 21 24 26 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 65 29 0 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 183 82 0 +220 97 0 237 111 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 147 68 0 8 5 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 86 43 0 236 108 0 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 237 110 1 237 110 1 237 111 1 +190 88 0 227 107 1 237 110 1 237 110 1 237 110 1 237 110 1 +237 110 1 237 110 1 237 110 1 158 78 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1203,22 +1050,21 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -18 24 27 173 86 8 249 114 0 236 112 1 236 112 1 236 112 1 -236 112 1 236 112 1 240 113 0 196 92 5 14 22 27 4 17 28 -148 72 11 225 114 1 249 114 0 236 112 1 236 112 1 236 112 1 -236 112 1 236 112 1 236 112 1 236 112 1 236 112 1 236 112 1 -237 111 1 249 114 0 237 112 0 111 56 15 108 69 17 240 113 0 -249 114 0 237 112 0 236 112 1 236 112 1 236 112 1 236 112 1 -236 112 1 236 112 1 236 112 1 236 112 1 237 112 0 249 114 0 -225 114 1 111 56 15 9 20 28 18 24 27 225 114 1 240 113 0 -236 112 1 236 112 1 236 112 1 236 112 1 236 112 1 249 114 0 -148 72 11 18 24 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 53 25 0 237 112 1 237 112 1 237 112 1 +237 112 1 237 112 1 237 112 1 237 112 1 237 112 1 98 43 0 +13 8 0 192 97 1 237 112 1 237 112 1 237 112 1 237 112 1 +237 112 1 237 112 1 237 112 1 237 112 1 237 112 1 237 112 1 +237 112 1 237 112 1 237 112 1 204 100 1 57 27 0 0 0 0 +0 0 0 10 6 0 147 68 0 237 112 1 237 112 1 237 112 1 +237 112 1 237 112 1 237 112 1 237 112 1 237 112 1 237 112 1 +237 112 1 237 112 1 237 112 1 237 112 1 237 112 1 86 43 0 +4 2 0 227 107 1 237 112 1 237 112 1 237 112 1 237 112 1 +237 112 1 237 112 1 237 112 1 147 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1253,23 +1099,22 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -16 21 27 173 86 8 247 119 0 237 114 1 237 114 1 237 114 1 -237 114 1 237 114 1 249 114 0 198 112 6 35 31 25 18 24 27 -18 24 27 85 50 19 196 92 5 247 119 0 237 114 1 237 114 1 -237 114 1 237 114 1 237 114 1 237 114 1 237 114 1 237 114 1 -237 114 1 237 114 1 240 113 0 238 116 1 240 113 0 240 113 0 -237 114 1 237 114 1 237 114 1 237 114 1 237 114 1 237 114 1 -237 114 1 237 114 1 237 114 1 237 115 0 247 119 0 196 92 5 -69 44 21 18 24 27 14 22 27 43 33 24 225 114 1 240 113 0 -237 114 1 237 114 1 237 114 1 237 114 1 237 114 1 247 119 0 -148 72 11 17 22 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 43 21 0 237 113 1 237 113 1 237 113 1 +237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 173 76 0 +0 0 0 0 0 0 147 68 0 237 113 1 237 113 1 237 113 1 +237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 +237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 118 52 0 +79 40 0 220 97 0 237 113 1 237 113 1 237 113 1 237 113 1 +237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 +237 113 1 237 113 1 237 113 1 204 100 1 48 22 0 0 0 0 +36 16 0 237 113 1 237 113 1 237 113 1 237 113 1 237 113 1 +237 113 1 237 113 1 237 113 1 138 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1303,17 +1148,73 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -9 20 28 173 86 8 247 119 0 238 116 1 238 116 1 238 116 1 -238 116 1 238 116 1 238 118 0 225 114 1 43 33 24 18 23 27 -22 25 27 17 22 27 43 33 24 173 86 8 252 126 0 247 119 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 31 17 0 238 115 1 238 115 1 238 115 1 +238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 179 91 1 +0 0 0 0 0 0 0 0 0 83 40 0 227 107 1 238 115 1 +238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 +238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 +238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 +238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 +238 115 1 238 115 1 147 68 0 0 0 0 0 0 0 0 0 0 +65 29 0 238 115 1 238 115 1 238 115 1 238 115 1 238 115 1 +238 115 1 238 115 1 238 115 1 127 63 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 22 12 0 237 114 1 238 116 1 238 116 1 +238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 192 97 1 +0 0 0 0 0 0 0 0 0 0 0 0 22 12 0 179 91 1 +238 117 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 -238 116 1 238 116 1 238 116 1 238 117 1 238 117 1 238 117 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 -238 116 1 238 116 1 247 119 0 252 126 0 148 72 11 43 33 24 -14 22 27 22 25 27 18 23 27 57 39 22 236 112 1 238 117 1 -238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 252 126 0 -119 81 15 14 20 27 23 25 27 0 0 0 0 0 0 0 0 0 +238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 +230 112 1 83 40 0 0 0 0 0 0 0 0 0 0 0 0 0 +83 40 0 238 116 1 238 116 1 238 116 1 238 116 1 238 116 1 +238 116 1 238 116 1 238 116 1 110 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1353,17 +1254,17 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -10 17 28 148 89 12 247 119 0 238 117 1 238 117 1 238 117 1 -238 117 1 238 117 1 238 118 0 238 116 1 43 33 24 18 24 27 -24 26 27 23 25 27 18 24 27 14 22 27 111 56 15 236 112 1 -247 119 0 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 6 0 227 107 1 238 117 1 238 117 1 +238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 204 100 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +118 52 0 238 118 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 -238 118 0 247 119 0 225 114 1 85 50 19 9 20 28 18 24 27 -23 25 27 24 26 27 18 23 27 69 44 21 238 119 0 238 118 0 -238 117 1 238 117 1 238 117 1 238 117 1 238 116 1 252 126 0 -111 56 15 9 20 28 23 25 27 0 0 0 0 0 0 0 0 0 +238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 179 91 1 +26 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +110 51 0 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 +238 117 1 238 117 1 238 117 1 101 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1404,17 +1305,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -9 20 28 148 72 11 247 119 0 237 120 0 238 117 1 238 117 1 -238 117 1 238 117 1 238 118 0 247 119 0 46 40 24 20 22 26 -24 26 27 24 26 27 24 26 27 22 25 27 14 22 27 35 31 25 -198 112 6 252 126 0 238 117 1 238 117 1 238 117 1 238 117 1 -238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 -238 117 1 238 117 1 238 117 1 238 117 1 238 117 1 238 118 0 -252 126 0 173 86 8 43 33 24 14 22 27 22 25 27 24 26 27 -24 26 27 24 26 27 14 22 27 85 50 19 247 119 0 238 119 0 -238 117 1 238 117 1 238 117 1 238 117 1 238 118 0 252 126 0 -111 56 15 18 24 27 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 3 2 0 206 109 2 238 118 1 238 118 1 +238 118 1 238 118 1 238 118 1 238 118 1 238 118 1 216 117 2 +3 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 48 22 0 204 100 1 238 119 1 238 118 1 238 118 1 +238 118 1 238 118 1 238 118 1 238 118 1 238 118 1 238 118 1 +238 118 1 238 118 1 238 118 1 238 118 1 238 118 1 238 118 1 +238 118 1 238 118 1 238 118 1 238 119 1 110 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 63 1 238 118 1 238 118 1 238 118 1 238 118 1 238 118 1 +238 118 1 238 118 1 238 118 1 86 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1454,18 +1354,17 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 17 28 119 81 15 242 125 0 238 119 0 237 120 0 237 120 0 -237 120 0 237 120 0 238 119 0 247 119 0 46 40 24 18 23 27 -24 26 27 24 26 27 24 26 27 24 26 27 23 25 27 18 22 27 -21 23 27 148 72 11 252 126 0 242 125 0 238 119 0 237 120 0 -237 120 0 237 120 0 237 120 0 237 120 0 237 120 0 237 120 0 -237 120 0 237 120 0 237 120 0 238 119 0 246 126 1 252 126 0 -108 69 17 18 24 27 18 24 27 23 25 27 24 26 27 24 26 27 -24 26 27 24 26 27 17 22 27 85 50 19 246 126 1 238 119 0 -237 120 0 237 120 0 237 120 0 237 120 0 238 118 0 252 126 0 -86 62 19 14 22 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 204 100 1 238 120 1 238 120 1 +238 120 1 238 120 1 238 120 1 238 120 1 238 120 1 230 112 1 +10 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 0 138 64 0 238 120 1 238 120 1 +238 120 1 238 120 1 238 120 1 238 120 1 238 120 1 238 120 1 +238 120 1 238 120 1 238 120 1 238 120 1 238 120 1 238 120 1 +238 120 1 238 120 1 204 100 1 53 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +140 77 1 238 120 1 238 120 1 238 120 1 238 120 1 238 120 1 +238 120 1 238 120 1 238 120 1 75 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -1504,1716 +1403,1669 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -13 20 27 111 56 15 238 119 0 238 119 0 237 120 0 237 120 0 -237 120 0 237 120 0 239 123 2 252 126 0 57 39 22 18 23 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -21 23 27 9 20 28 69 44 21 225 114 1 246 126 1 239 123 2 -237 120 0 237 120 0 237 120 0 237 120 0 237 120 0 237 120 0 -237 120 0 237 120 0 242 125 0 252 126 0 196 92 5 69 44 21 -4 17 28 23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 14 22 27 86 62 19 252 126 0 237 120 0 -237 120 0 237 120 0 237 120 0 237 120 0 237 120 0 252 126 0 -69 44 21 18 22 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 192 97 1 238 121 1 238 121 1 +238 121 1 238 121 1 238 121 1 238 121 1 238 121 1 236 120 1 +22 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 79 40 0 230 112 1 +238 122 1 238 121 1 238 121 1 238 121 1 238 121 1 238 121 1 +238 121 1 238 121 1 238 121 1 238 121 1 238 121 1 238 122 1 +238 122 1 140 77 1 3 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +147 76 1 238 121 1 238 121 1 238 121 1 238 121 1 238 121 1 +238 121 1 238 121 1 238 121 1 61 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 21 23 24 -21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 26 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 26 21 23 24 19 21 23 -19 21 22 16 18 19 15 17 18 15 17 18 16 18 19 18 20 22 -19 21 22 20 22 23 22 24 25 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 26 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 21 23 24 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 23 25 26 0 0 0 0 0 0 22 24 25 -21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 21 23 24 21 23 24 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 21 23 24 -19 21 23 18 20 22 16 18 19 15 17 18 15 17 18 17 19 21 -19 21 22 20 22 24 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 26 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 21 23 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 22 24 25 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 22 27 85 50 19 242 125 0 239 123 2 239 123 2 239 123 2 -239 123 2 239 123 2 239 123 2 252 137 0 57 39 22 17 22 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 23 25 27 9 20 28 43 33 24 148 89 12 237 120 0 -252 126 0 242 125 0 239 123 2 239 123 2 239 123 2 239 123 2 -242 125 0 246 126 1 233 126 1 148 72 11 35 31 25 14 22 27 -23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 13 20 27 111 56 15 252 126 0 239 123 2 -239 123 2 239 123 2 239 123 2 239 123 2 239 123 2 246 126 1 -57 39 22 18 23 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 26 23 25 26 30 32 33 -31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 26 28 30 -22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -22 24 25 31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 26 28 30 22 24 25 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 24 25 -26 28 30 31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 23 25 26 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 26 17 19 21 12 14 15 30 32 32 43 44 44 -47 49 49 75 76 76 85 86 85 85 86 85 85 86 85 51 52 52 -43 44 44 38 39 40 19 21 22 12 14 15 22 24 25 0 0 0 -0 0 0 23 25 26 22 24 25 31 33 34 31 33 34 31 33 34 -31 33 34 31 33 34 34 35 36 24 26 27 23 25 26 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 22 23 -26 28 30 31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 34 35 36 23 25 27 23 25 26 22 24 25 26 28 30 -34 35 36 31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 31 33 34 31 33 34 31 33 34 24 26 27 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 18 20 22 12 14 15 26 28 30 -43 44 44 47 49 49 85 86 85 85 86 85 85 86 85 63 65 64 -43 44 44 35 37 38 15 17 19 15 17 19 23 25 26 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -23 25 26 34 35 36 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 31 33 34 30 32 32 19 21 22 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 23 25 27 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 31 33 34 31 33 34 22 24 25 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -16 21 27 70 55 22 242 125 0 239 126 1 239 123 2 239 123 2 -239 123 2 239 123 2 239 123 2 252 137 0 85 50 19 14 22 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 23 25 27 18 23 27 17 21 27 85 50 19 -173 86 8 233 126 1 252 126 0 252 137 0 252 126 0 252 137 0 -225 114 1 173 86 8 70 55 22 4 17 28 18 24 27 22 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 13 20 27 108 69 17 252 126 0 239 126 1 -239 123 2 239 123 2 239 123 2 239 123 2 242 125 0 246 126 1 -43 33 24 18 24 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 167 167 162 -194 194 188 191 190 184 191 190 184 191 190 185 194 194 188 97 97 95 -15 17 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 32 167 167 162 194 194 188 191 190 184 191 190 184 191 190 184 -199 199 193 108 109 107 14 16 18 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 17 18 -97 97 95 194 194 188 191 190 185 191 190 184 191 190 184 194 194 188 -178 178 173 35 37 38 21 23 24 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -15 17 19 4 6 8 63 65 64 139 140 136 188 188 182 219 218 211 -228 227 220 226 224 218 225 224 217 224 222 216 224 222 216 227 226 219 -223 222 215 204 202 197 167 167 162 108 109 107 26 28 30 22 24 25 -0 0 0 22 24 25 26 27 26 191 190 185 191 190 185 191 190 184 -191 190 184 191 190 184 204 202 197 75 76 76 15 17 19 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 12 14 15 -178 178 173 194 194 188 191 190 184 191 190 184 191 190 184 191 190 184 -201 200 194 155 156 152 14 16 18 23 25 26 16 18 19 85 86 85 -204 202 197 191 190 184 191 190 184 191 190 184 191 190 184 191 190 184 -191 190 184 191 190 184 191 190 184 191 190 184 191 190 184 191 190 184 -191 190 184 191 190 184 191 190 185 199 199 193 75 76 76 17 19 21 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 26 18 20 22 1 3 5 47 49 49 123 124 122 186 185 180 -221 219 213 228 227 220 224 222 216 224 222 216 224 222 216 227 226 219 -225 224 217 201 200 194 155 156 152 75 76 76 5 8 10 15 17 19 -23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -16 18 19 155 156 152 199 199 193 191 190 184 191 190 184 191 190 184 -191 190 184 191 190 185 188 188 182 20 22 24 21 23 24 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -8 10 12 123 124 122 199 199 193 191 190 184 191 190 184 191 190 184 -191 190 185 199 199 193 123 124 122 14 16 18 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -17 22 27 69 44 21 239 123 2 242 125 0 239 126 1 239 126 1 -239 126 1 239 126 1 239 126 1 252 126 0 108 69 17 13 20 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 22 25 27 14 22 27 -9 20 28 43 33 24 58 46 23 69 44 21 69 44 21 58 46 23 -35 31 25 4 17 28 16 21 27 23 25 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 23 25 27 9 20 28 148 72 11 252 137 0 239 126 1 -239 126 1 239 126 1 239 126 1 239 126 1 239 126 1 242 125 0 -29 29 28 21 23 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 33 191 190 185 -218 216 210 213 212 206 213 212 206 214 213 207 221 220 213 108 109 107 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -31 33 34 191 190 185 218 216 210 213 212 206 213 212 206 213 212 206 -226 224 218 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -108 109 107 221 220 213 214 213 207 213 212 206 213 212 206 217 215 209 -204 202 197 35 37 38 20 22 24 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 5 8 10 -75 76 76 191 190 184 228 227 220 219 218 211 214 213 207 211 210 204 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 212 211 205 219 218 211 222 221 214 43 44 44 20 22 23 -0 0 0 21 23 24 26 28 30 217 216 210 215 214 208 213 212 206 -213 212 206 213 212 206 228 227 220 75 76 76 16 18 19 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 26 17 19 21 123 124 122 -226 224 218 214 212 206 213 212 206 213 212 206 213 212 206 219 218 211 -199 199 193 34 35 36 20 22 23 24 26 27 14 16 17 100 100 100 -227 226 219 213 212 206 213 212 206 213 212 206 213 212 206 213 212 206 -213 212 206 213 212 206 213 212 206 213 212 206 213 212 206 213 212 206 -213 212 206 213 212 206 214 213 207 223 222 215 85 86 85 15 17 19 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -9 12 13 51 52 52 167 167 162 236 234 227 222 221 214 214 213 207 -211 210 204 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 213 212 206 217 216 210 228 227 220 194 194 188 75 76 76 -5 8 10 22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 -15 17 19 63 65 64 218 216 210 215 214 208 213 212 206 213 212 206 -213 212 206 214 212 206 226 224 218 115 115 113 14 16 18 23 25 26 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 21 22 -51 52 52 210 209 203 216 215 208 213 212 206 213 212 206 213 212 206 -219 218 211 194 194 188 34 35 36 20 22 24 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -17 22 27 58 46 23 239 126 1 239 126 1 239 126 1 239 126 1 -239 126 1 239 126 1 239 126 1 252 137 0 148 72 11 4 17 28 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 18 24 27 18 23 27 17 22 27 16 21 27 18 23 27 -21 23 27 23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 4 17 28 173 86 8 245 138 1 239 126 1 -239 126 1 239 126 1 239 126 1 239 126 1 239 126 1 241 129 1 -26 27 26 21 23 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 18 20 22 24 26 27 123 124 122 -224 222 216 215 214 208 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 211 210 204 212 210 204 38 39 40 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 0 0 0 -0 0 0 0 0 0 23 25 26 14 16 17 75 76 76 215 213 207 -212 211 205 210 209 203 210 209 203 210 209 203 211 210 204 222 221 214 -63 65 64 17 19 21 23 25 26 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 220 219 212 85 86 85 15 17 19 -0 0 0 0 0 0 0 0 0 0 0 0 22 24 25 10 13 14 -100 100 100 208 207 200 219 218 211 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 215 214 208 221 219 213 -115 115 113 19 21 23 21 23 24 0 0 0 0 0 0 0 0 0 -23 25 26 14 16 18 123 124 122 224 222 216 210 209 203 210 209 203 -210 209 203 210 209 203 214 213 206 191 190 185 34 35 36 20 22 23 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 8 10 12 -155 156 152 217 215 209 210 209 203 210 209 203 210 209 203 210 209 203 -219 218 211 97 97 95 12 14 15 23 25 26 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -13 20 27 85 50 19 241 129 1 241 129 1 241 129 1 252 137 0 -252 137 0 252 137 0 252 137 0 252 137 0 119 81 15 9 20 28 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 9 20 28 173 86 8 252 137 0 252 137 0 -252 137 0 252 137 0 252 137 0 241 129 1 241 129 1 241 129 1 -43 33 24 18 23 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 19 21 22 21 23 24 167 167 162 226 224 218 -211 210 204 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 211 210 204 212 210 204 43 44 44 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 0 0 0 -0 0 0 0 0 0 21 23 24 22 24 25 186 185 180 217 215 209 -210 209 203 210 209 203 210 209 203 210 209 203 223 222 215 123 124 122 -4 6 8 23 25 26 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 219 218 211 85 86 85 15 17 19 -0 0 0 0 0 0 0 0 0 22 24 25 12 14 15 100 100 100 -227 226 219 213 212 206 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 211 210 204 -222 221 214 139 140 136 10 13 14 22 24 25 0 0 0 0 0 0 -0 0 0 21 23 24 23 25 27 218 216 210 212 211 205 210 209 203 -210 209 203 210 209 203 210 209 203 222 220 214 104 105 103 10 13 14 -0 0 0 0 0 0 0 0 0 0 0 0 17 19 21 51 52 52 -224 222 216 211 210 204 210 209 203 210 209 203 210 209 203 219 218 211 -167 167 162 17 19 21 22 24 25 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -10 17 28 148 89 12 252 137 0 252 137 0 233 126 1 148 89 12 -119 81 15 29 29 28 4 11 29 4 11 29 14 22 27 26 27 26 -23 25 27 23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 23 25 27 22 25 27 9 20 28 4 17 28 4 11 29 -35 31 25 119 81 15 173 86 8 239 126 1 252 137 0 252 137 0 -119 81 15 12 18 27 23 25 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 0 0 0 -0 0 0 20 22 24 14 16 17 189 188 183 221 220 213 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 211 210 204 215 214 208 -222 221 214 226 224 218 223 222 215 223 222 215 224 222 216 227 226 219 -222 220 214 217 215 209 214 213 207 212 210 204 38 39 40 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 0 0 0 -0 0 0 23 25 26 1 3 5 155 156 152 219 218 211 210 209 203 -210 209 203 210 209 203 210 209 203 220 219 212 155 156 152 18 20 22 -22 25 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 212 211 205 -228 227 220 228 227 220 228 227 220 228 227 220 228 227 220 228 227 220 -228 227 220 228 227 220 228 227 220 236 234 227 85 86 85 17 19 21 -0 0 0 0 0 0 23 25 26 10 13 14 106 107 104 227 226 219 -211 210 204 210 209 203 210 209 203 210 209 203 210 209 203 211 210 204 -217 215 209 224 222 216 225 224 217 223 222 215 223 222 215 226 224 218 -217 215 209 211 210 204 210 209 203 210 209 203 210 209 203 210 209 203 -211 210 204 222 221 214 123 124 122 5 8 10 23 25 26 0 0 0 -0 0 0 0 0 0 10 13 14 100 100 100 219 218 211 210 209 203 -210 209 203 210 209 203 210 209 203 214 213 207 194 194 188 31 33 34 -20 22 23 0 0 0 0 0 0 22 24 25 19 21 22 167 167 162 -217 216 210 210 209 203 210 209 203 210 209 203 212 211 205 222 220 214 -35 37 38 18 20 22 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 27 -35 31 25 198 112 6 198 112 6 69 44 21 35 31 25 12 18 27 -12 18 27 21 23 27 22 25 27 18 23 27 18 23 27 18 23 27 -18 23 27 18 23 27 18 23 27 21 23 27 23 25 27 23 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 23 25 27 23 25 27 21 23 27 18 23 27 -18 22 27 18 23 27 17 22 27 17 22 27 18 24 27 22 25 27 -21 23 27 12 18 27 9 20 28 35 31 25 86 62 19 198 112 6 -173 86 8 35 31 25 21 23 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 0 0 0 -22 24 25 17 19 21 139 140 136 222 221 214 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 214 213 207 216 215 208 178 178 173 -108 109 107 47 49 49 43 44 44 47 48 48 43 44 44 51 52 52 -115 115 113 167 167 162 208 207 200 222 220 214 43 44 44 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 0 0 0 -23 25 26 15 17 19 75 76 76 224 222 216 211 210 204 210 209 203 -210 209 203 210 209 203 214 213 207 194 194 188 38 39 40 18 20 22 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 204 202 197 -30 32 33 47 48 48 47 48 48 47 48 48 47 48 48 47 48 48 -47 48 48 47 48 48 47 49 49 51 52 52 31 33 34 22 24 25 -0 0 0 0 0 0 15 17 19 63 65 64 208 207 200 213 212 206 -210 209 203 210 209 203 210 209 203 210 209 203 213 212 206 216 215 208 -167 167 162 75 76 76 43 44 44 43 44 44 43 44 44 63 65 64 -167 167 162 212 211 205 214 213 206 210 209 203 210 209 203 210 209 203 -210 209 203 211 210 204 224 222 216 63 65 64 17 19 21 23 25 26 -0 0 0 0 0 0 21 23 24 23 25 27 178 178 173 217 215 209 -210 209 203 210 209 203 210 209 203 210 209 203 216 216 210 106 108 104 -12 14 15 0 0 0 0 0 0 15 17 18 75 76 76 217 216 210 -211 210 204 210 209 203 210 209 203 210 209 203 221 219 213 123 124 122 -8 10 12 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 27 -46 40 24 57 39 22 4 17 28 13 20 27 18 23 27 18 22 27 -12 18 27 10 17 28 14 20 27 35 31 25 57 39 22 58 46 23 -58 46 23 57 39 22 43 33 24 26 27 26 9 20 28 10 17 28 -16 21 27 21 23 27 23 25 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 23 25 27 -18 23 27 14 20 27 10 17 28 10 17 28 26 27 26 46 40 24 -57 39 22 58 46 23 57 39 22 46 40 24 35 31 25 14 22 27 -9 20 28 13 20 27 17 22 27 18 23 27 13 20 27 4 17 28 -70 55 22 43 33 24 22 25 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 0 0 0 -13 15 16 75 76 76 222 220 214 211 210 204 210 209 203 210 209 203 -210 209 203 210 209 203 219 218 211 204 202 197 75 76 76 12 14 15 -12 14 15 18 20 22 19 21 22 19 21 22 19 21 22 18 20 22 -12 14 15 8 10 12 47 49 49 139 140 136 43 44 44 20 22 24 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 0 0 0 -19 21 22 31 33 34 194 194 188 215 213 207 210 209 203 210 209 203 -210 209 203 211 210 204 228 227 220 63 65 64 17 19 21 23 25 26 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -1 3 5 19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 22 19 21 22 19 21 22 22 24 25 0 0 0 -0 0 0 23 25 26 1 3 5 178 178 173 217 215 209 210 209 203 -210 209 203 210 209 203 210 209 203 215 213 207 210 209 203 85 86 85 -1 3 5 15 17 19 19 21 22 19 21 22 19 21 22 16 18 19 -5 8 10 75 76 76 208 207 200 214 213 207 210 209 203 210 209 203 -210 209 203 210 209 203 217 216 210 167 167 162 20 22 23 22 24 25 -0 0 0 0 0 0 0 0 0 14 16 17 75 76 76 220 219 212 -211 210 204 210 209 203 210 209 203 210 209 203 214 213 207 199 199 193 -8 10 12 22 24 25 22 24 25 20 22 23 178 178 173 217 215 209 -210 209 203 210 209 203 210 209 203 215 214 208 191 190 185 30 32 32 -21 23 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -21 23 27 18 23 27 21 23 27 10 17 28 21 23 27 58 46 23 -119 81 15 178 116 9 198 112 6 238 145 2 252 154 1 252 154 1 -252 154 1 252 154 1 252 137 0 198 112 6 178 116 9 173 86 8 -69 44 21 43 33 24 9 20 28 17 22 27 22 25 27 23 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 23 25 27 22 25 27 16 21 27 10 17 28 -46 40 24 86 62 19 153 108 13 178 116 9 227 131 4 252 154 1 -252 154 1 252 154 1 252 154 1 249 147 1 227 131 4 198 112 6 -173 86 8 108 69 17 57 39 22 16 21 27 13 20 27 21 23 27 -18 22 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 21 23 24 -26 28 30 191 190 185 215 214 208 210 209 203 210 209 203 210 209 203 -210 209 203 217 215 209 188 188 182 14 16 17 13 15 17 23 25 26 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 26 19 21 22 12 14 15 21 23 24 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 22 24 25 -14 16 17 155 156 152 221 220 213 210 209 203 210 209 203 210 209 203 -210 209 203 222 220 214 115 115 113 5 8 10 23 25 26 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 204 202 197 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 26 14 16 17 85 86 85 228 227 220 210 209 203 210 209 203 -210 209 203 210 209 203 212 211 205 208 207 200 51 52 52 9 12 13 -23 25 26 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 26 9 12 13 43 44 44 217 216 210 212 211 205 210 209 203 -210 209 203 210 209 203 210 209 203 225 224 217 85 86 85 14 16 17 -0 0 0 0 0 0 0 0 0 22 24 25 15 17 19 139 140 136 -221 220 213 210 209 203 210 209 203 210 209 203 210 209 203 226 224 218 -97 97 95 14 16 18 12 14 15 100 100 100 218 216 210 210 209 203 -210 209 203 210 209 203 211 210 204 220 219 212 75 76 76 13 15 16 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 25 27 14 20 27 26 27 26 119 81 15 178 116 9 238 145 2 -244 155 3 252 154 1 246 155 2 242 147 2 242 147 2 245 138 1 -239 136 1 245 138 1 239 136 1 252 137 0 246 126 1 245 138 1 -233 126 1 198 112 6 148 72 11 46 40 24 18 23 27 18 24 27 -23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 23 25 27 18 23 27 18 22 27 70 55 22 148 89 12 -228 138 5 242 153 2 252 154 1 252 154 1 249 147 1 242 147 2 -245 138 1 239 136 1 245 138 1 239 133 2 245 138 1 245 138 1 -252 137 0 241 129 1 233 126 1 173 86 8 86 62 19 26 27 26 -14 22 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 14 16 17 -100 100 100 217 215 209 210 209 203 210 209 203 210 209 203 210 209 203 -214 213 207 194 194 188 47 49 49 16 18 19 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 12 14 15 -97 97 95 213 212 206 211 210 204 210 209 203 210 209 203 210 209 203 -219 218 211 155 156 152 20 22 23 22 24 25 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 22 24 25 155 156 152 218 216 210 210 209 203 210 209 203 -210 209 203 210 209 203 223 222 215 100 100 100 14 16 18 23 25 26 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 23 25 26 8 10 12 115 115 113 216 216 210 210 209 203 -210 209 203 210 209 203 210 209 203 217 216 210 155 156 152 14 16 17 -23 25 26 0 0 0 0 0 0 0 0 0 19 21 22 35 37 38 -216 215 208 212 211 205 210 209 203 210 209 203 210 209 203 215 213 207 -186 185 180 26 28 30 15 17 18 201 200 194 213 212 206 210 209 203 -210 209 203 210 209 203 219 218 211 155 156 152 16 18 19 22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 18 22 27 -10 17 28 86 62 19 198 140 8 251 162 2 250 164 3 246 155 2 -243 153 2 242 151 2 242 147 2 242 147 2 242 147 2 239 136 1 -245 138 1 239 136 1 239 133 2 239 133 2 239 133 2 241 129 1 -241 129 1 246 126 1 252 137 0 225 114 1 148 72 11 26 27 26 -9 20 28 22 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -22 25 27 10 17 28 26 27 26 178 116 9 239 160 4 254 162 1 -247 162 2 243 152 2 243 152 2 242 151 2 242 147 2 238 145 2 -245 138 1 238 145 2 239 136 1 239 136 1 239 133 2 239 133 2 -241 129 1 239 126 1 239 126 1 252 126 0 242 125 0 196 92 5 -69 44 21 9 20 28 18 24 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 0 0 0 1 3 5 -186 185 180 215 214 208 210 209 203 210 209 203 210 209 203 210 209 203 -222 221 214 85 86 85 9 12 13 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 12 14 15 21 23 24 -210 209 203 214 213 206 210 209 203 210 209 203 210 209 203 214 213 207 -201 200 194 47 48 48 17 19 21 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -19 21 23 43 44 44 208 207 200 212 211 205 210 209 203 210 209 203 -210 209 203 213 212 206 204 202 197 10 13 14 22 24 25 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 20 22 23 35 37 38 199 199 193 213 212 206 -210 209 203 210 209 203 210 209 203 214 212 206 201 200 194 43 44 44 -20 22 23 0 0 0 0 0 0 0 0 0 0 0 0 8 10 12 -123 124 122 220 219 212 210 209 203 210 209 203 210 209 203 210 209 203 -220 219 212 75 76 76 85 86 85 226 224 218 210 209 203 210 209 203 -210 209 203 212 211 205 223 222 215 34 35 36 18 20 22 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 22 25 27 13 20 27 35 31 25 -198 140 8 250 168 2 254 162 1 244 158 4 244 157 4 242 153 2 -243 152 2 242 151 2 242 147 2 242 147 2 242 147 2 239 136 1 -238 145 2 245 138 1 239 133 2 239 133 2 241 129 1 241 129 1 -239 126 1 239 123 2 239 123 2 242 125 0 252 126 0 252 126 0 -85 50 19 9 20 28 21 23 27 23 25 27 23 25 27 18 23 27 -12 18 27 119 81 15 249 174 4 254 162 1 248 161 3 244 157 4 -241 156 2 243 152 2 243 152 2 242 147 2 242 147 2 242 147 2 -245 138 1 239 136 1 245 138 1 239 133 2 239 136 1 241 129 1 -241 129 1 239 126 1 239 126 1 239 123 2 239 123 2 246 126 1 -252 126 0 173 86 8 35 31 25 13 20 27 23 25 27 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 20 22 23 38 39 40 -219 218 211 211 210 204 210 209 203 210 209 203 210 209 203 215 214 208 -178 178 173 22 24 25 21 23 24 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 9 12 13 167 167 162 -219 218 211 210 209 203 210 209 203 210 209 203 212 211 205 222 221 214 -63 65 64 12 14 15 23 25 26 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -1 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 16 17 97 97 95 222 220 214 210 209 203 210 209 203 210 209 203 -210 209 203 217 216 210 115 115 113 10 13 14 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 5 8 10 139 140 136 219 218 211 -210 209 203 210 209 203 210 209 203 210 209 203 217 215 209 85 86 85 -15 17 18 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -23 25 26 186 185 180 217 215 209 210 209 203 210 209 203 210 209 203 -215 214 208 167 167 162 155 156 152 217 215 209 210 209 203 210 209 203 -210 209 203 219 218 211 115 115 113 8 10 12 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 27 12 18 27 86 62 19 239 160 4 -250 168 3 247 162 2 244 158 4 244 158 4 244 157 4 242 153 2 -243 152 2 242 151 2 242 147 2 242 147 2 242 147 2 238 145 2 -245 138 1 239 136 1 239 133 2 239 133 2 239 133 2 239 126 1 -241 129 1 239 123 2 239 123 2 237 120 0 238 117 1 238 118 0 -247 119 0 173 86 8 16 21 27 18 24 27 18 22 27 21 23 27 -198 140 8 250 168 2 250 164 3 244 158 4 244 158 4 244 157 4 -244 155 3 242 151 2 243 152 2 242 147 2 238 145 2 242 147 2 -245 138 1 238 145 2 239 136 1 239 136 1 239 133 2 239 133 2 -239 133 2 239 126 1 239 123 2 239 123 2 239 123 2 238 117 1 -238 118 0 247 119 0 223 98 1 57 39 22 16 21 27 23 25 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 16 18 19 75 76 76 -225 224 217 210 209 203 210 209 203 210 209 203 210 209 203 222 220 214 -108 109 107 14 16 17 23 25 26 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 226 224 218 63 65 64 97 97 95 219 218 211 -210 209 203 210 209 203 210 209 203 210 209 203 219 218 211 123 124 122 -5 8 10 23 25 26 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 204 202 197 -0 0 0 13 15 16 13 15 16 13 15 16 13 15 16 13 15 16 -13 15 16 13 15 16 13 15 16 18 20 22 0 0 0 0 0 0 -9 12 13 139 140 136 219 218 211 210 209 203 210 209 203 210 209 203 -211 210 204 211 210 204 63 65 64 17 19 21 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 17 19 21 85 86 85 219 218 211 -210 209 203 210 209 203 210 209 203 210 209 203 218 216 210 115 115 113 -12 14 15 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -13 15 16 85 86 85 217 215 209 211 210 204 210 209 203 210 209 203 -210 209 203 208 207 200 208 207 200 210 209 203 210 209 203 210 209 203 -217 215 209 178 178 173 26 28 30 21 23 24 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 22 25 27 4 11 29 108 69 17 249 174 4 250 168 3 -245 163 4 244 163 4 244 157 4 244 158 4 244 157 4 242 153 2 -243 152 2 242 151 2 242 147 2 242 147 2 245 138 1 239 136 1 -238 145 2 245 138 1 239 133 2 239 133 2 239 133 2 241 129 1 -239 126 1 239 123 2 239 123 2 237 120 0 238 117 1 238 117 1 -240 113 0 247 119 0 196 92 5 4 17 28 26 27 26 198 140 8 -251 178 1 250 164 3 245 163 4 244 158 4 244 158 4 244 158 4 -241 156 2 242 151 2 243 152 2 242 151 2 242 147 2 242 147 2 -245 138 1 238 145 2 239 136 1 245 138 1 239 133 2 239 133 2 -241 129 1 239 126 1 239 123 2 239 126 1 239 123 2 237 117 0 -238 117 1 238 117 1 247 119 0 236 112 1 69 44 21 9 20 28 -23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 0 0 0 12 14 15 106 108 104 -222 221 214 210 209 203 210 209 203 210 209 203 210 209 203 224 222 216 -75 76 76 15 17 18 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 221 220 213 97 97 95 194 194 188 214 213 206 -210 209 203 210 209 203 210 209 203 220 219 212 167 167 162 18 20 22 -23 25 26 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 211 210 204 204 202 197 -100 100 100 108 109 107 108 109 107 108 109 107 108 109 107 108 109 107 -108 109 107 108 109 107 115 115 113 63 65 64 18 20 22 23 25 26 -8 10 12 155 156 152 217 216 210 210 209 203 210 209 203 210 209 203 -212 211 205 199 199 193 47 48 48 19 21 22 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 18 20 22 51 52 52 217 215 209 -211 210 204 210 209 203 210 209 203 210 209 203 217 215 209 139 140 136 -12 14 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 18 20 22 167 167 162 217 216 210 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 211 210 204 -221 220 213 75 76 76 14 16 17 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 25 27 9 20 28 119 81 15 252 181 4 245 167 3 244 163 4 -245 163 4 244 163 4 244 158 4 244 158 4 244 157 4 242 153 2 -243 152 2 242 151 2 242 147 2 242 147 2 242 147 2 238 145 2 -245 138 1 239 136 1 239 133 2 239 133 2 239 133 2 239 126 1 -239 126 1 239 126 1 239 123 2 237 120 0 238 117 1 238 117 1 -238 116 1 237 111 1 240 113 0 196 92 5 228 138 5 251 178 1 -245 167 3 245 163 4 245 163 4 244 158 4 244 158 4 244 157 4 -241 156 2 243 152 2 243 152 2 242 147 2 242 147 2 238 145 2 -245 138 1 239 136 1 245 138 1 239 133 2 239 133 2 241 129 1 -239 133 2 239 126 1 239 126 1 239 123 2 239 123 2 238 117 1 -238 117 1 238 116 1 236 112 1 240 113 0 249 114 0 85 50 19 -9 20 28 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 23 25 26 17 19 21 139 140 136 -219 218 211 210 209 203 210 209 203 210 209 203 210 209 203 221 220 213 -38 39 40 19 21 23 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 212 211 205 178 178 173 214 213 206 210 209 203 -210 209 203 210 209 203 214 212 206 186 185 180 26 28 30 18 20 22 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 211 210 204 -223 222 215 222 220 214 224 222 216 224 222 216 224 222 216 224 222 216 -224 222 216 222 220 214 236 234 227 123 124 122 12 14 15 22 24 25 -21 24 26 178 178 173 215 214 208 210 209 203 210 209 203 210 209 203 -214 213 206 188 188 182 30 32 33 21 23 24 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 20 22 23 38 39 40 208 207 200 -212 211 205 210 209 203 210 209 203 210 209 203 219 218 211 155 156 152 -8 10 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 18 20 22 38 39 40 220 219 212 211 210 204 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 218 216 210 -139 140 136 14 16 17 23 25 26 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -12 18 27 108 69 17 248 180 4 249 174 4 245 167 3 243 165 4 -245 163 4 244 163 4 244 157 4 244 158 4 244 157 4 242 153 2 -243 152 2 242 151 2 242 147 2 242 147 2 242 147 2 239 136 1 -245 138 1 239 136 1 239 133 2 239 133 2 239 133 2 241 129 1 -239 126 1 239 123 2 239 123 2 237 120 0 238 117 1 238 117 1 -238 116 1 237 110 0 237 111 1 245 163 4 245 174 5 244 167 4 -245 167 3 245 163 4 245 163 4 244 158 4 244 158 4 244 158 4 -241 156 2 242 151 2 243 152 2 242 151 2 242 147 2 242 147 2 -238 145 2 238 145 2 239 136 1 239 136 1 239 136 1 239 133 2 -241 129 1 239 126 1 239 123 2 239 123 2 239 123 2 237 117 0 -238 117 1 238 116 1 236 112 1 237 111 1 240 113 0 249 107 0 -69 44 21 14 22 27 23 25 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 21 24 26 19 21 22 139 140 136 -221 219 213 210 209 203 210 209 203 210 209 203 211 210 204 216 215 208 -30 32 33 21 23 24 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 210 209 203 211 210 204 211 210 204 210 209 203 -210 209 203 210 209 203 213 212 206 189 188 183 35 37 38 18 20 22 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 222 220 214 115 115 113 12 14 15 21 23 24 -30 32 32 186 185 180 213 213 206 210 209 203 210 209 203 210 209 203 -215 213 207 178 178 173 21 24 26 22 24 25 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 20 22 23 35 37 38 201 200 194 -212 211 205 210 209 203 210 209 203 210 209 203 217 215 209 178 178 173 -5 8 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 26 4 6 8 155 156 152 212 211 205 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 218 216 210 -43 44 44 15 17 19 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 22 27 -58 46 23 239 160 4 249 174 4 245 167 3 245 170 5 244 163 4 -245 163 4 244 163 4 244 158 4 244 158 4 244 157 4 242 153 2 -243 152 2 242 151 2 249 147 1 252 154 1 249 147 1 252 154 1 -252 154 1 249 147 1 252 137 0 245 138 1 241 129 1 241 129 1 -239 126 1 239 126 1 239 123 2 237 120 0 238 117 1 238 117 1 -237 114 1 237 109 1 242 151 2 248 180 4 245 167 3 244 167 4 -244 167 4 245 163 4 245 163 4 244 158 4 244 158 4 244 157 4 -244 155 3 242 151 2 242 151 2 242 151 2 249 147 1 252 154 1 -249 147 1 249 147 1 252 154 1 252 137 0 252 137 0 239 133 2 -239 133 2 239 126 1 239 126 1 239 123 2 239 123 2 238 117 1 -238 117 1 238 116 1 236 112 1 237 111 1 237 109 1 249 107 0 -196 92 5 35 31 25 17 22 27 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 22 24 25 23 25 27 155 156 152 -217 216 210 210 209 203 210 209 203 210 209 203 211 210 204 217 216 210 -34 35 36 20 22 23 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 214 213 207 167 167 162 214 213 207 210 209 203 -210 209 203 210 209 203 210 209 203 219 218 211 155 156 152 9 12 13 -22 24 25 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 221 220 213 115 115 113 12 14 15 21 23 24 -30 32 32 186 185 180 214 213 207 210 209 203 210 209 203 210 209 203 -214 213 207 186 185 180 26 28 30 21 23 24 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 20 22 23 35 37 38 201 200 194 -212 211 205 210 209 203 210 209 203 210 209 203 217 215 209 155 156 152 -8 10 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 20 22 23 17 19 21 199 199 193 213 212 206 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 221 219 213 -123 124 122 14 16 17 23 25 26 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 21 23 27 16 21 27 -198 140 8 252 181 4 246 172 5 245 167 3 245 170 5 244 163 4 -245 163 4 244 163 4 244 157 4 244 158 4 244 157 4 243 153 2 -252 154 1 254 162 1 198 140 8 178 116 9 148 72 11 70 55 22 -70 55 22 108 69 17 173 86 8 178 116 9 252 137 0 252 137 0 -241 129 1 239 123 2 239 123 2 237 120 0 238 117 1 238 117 1 -237 110 0 239 136 1 245 174 5 246 172 5 245 167 3 244 167 4 -244 167 4 245 163 4 245 163 4 244 158 4 244 158 4 244 158 4 -241 156 2 246 155 2 254 162 1 242 147 2 178 116 9 153 108 13 -111 56 15 70 55 22 85 50 19 148 89 12 178 116 9 225 114 1 -252 137 0 241 129 1 239 126 1 239 123 2 239 123 2 237 117 0 -238 117 1 238 116 1 236 112 1 237 111 1 237 109 1 236 106 0 -249 107 0 173 86 8 21 23 27 22 25 27 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -106 107 104 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 23 25 26 17 19 21 139 140 136 -219 218 211 210 209 203 210 209 203 210 209 203 210 209 203 222 221 214 -47 48 48 19 21 22 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 222 220 214 85 86 85 191 190 185 215 213 207 -210 209 203 210 209 203 210 209 203 210 209 203 221 219 213 123 124 122 -5 8 10 23 25 26 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -214 213 207 214 213 207 214 213 207 214 213 207 214 213 207 214 213 207 -214 213 207 214 213 207 226 224 218 115 115 113 12 14 15 22 24 25 -21 23 24 178 178 173 214 213 207 210 209 203 210 209 203 210 209 203 -213 212 206 191 190 185 34 35 36 20 22 23 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 19 21 23 43 44 44 213 211 204 -211 210 204 210 209 203 210 209 203 210 209 203 217 215 209 139 140 136 -12 14 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 15 17 19 155 156 152 219 218 211 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 211 210 204 -220 219 212 63 65 64 15 17 18 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 18 24 27 119 81 15 -252 181 4 249 174 4 245 170 5 245 167 3 245 167 3 244 163 4 -245 163 4 244 163 4 244 158 4 244 158 4 244 158 4 254 162 1 -198 112 6 86 62 19 35 31 25 12 18 27 18 24 27 21 23 27 -20 22 26 17 22 27 17 22 27 20 22 26 57 39 22 148 89 12 -241 129 1 246 126 1 239 123 2 237 120 0 238 117 1 237 117 0 -237 117 0 246 172 5 245 174 5 246 172 5 245 167 3 244 167 4 -244 167 4 245 163 4 245 163 4 244 158 4 244 158 4 244 157 4 -254 162 1 242 147 2 119 81 15 57 39 22 21 23 27 17 21 27 -17 22 27 18 22 27 16 21 27 17 21 27 12 18 27 29 29 28 -108 69 17 198 112 6 252 126 0 242 125 0 239 123 2 238 117 1 -238 117 1 238 116 1 236 112 1 237 111 1 237 109 1 235 106 1 -238 106 0 236 99 0 111 56 15 9 20 28 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -30 32 33 189 188 183 214 213 206 210 209 203 210 209 203 210 209 203 -221 219 213 123 124 122 12 14 15 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 15 17 -104 105 103 216 216 210 210 209 203 210 209 203 210 209 203 212 211 205 -201 200 194 35 37 38 20 22 24 23 25 26 15 17 19 123 124 122 -221 219 213 210 209 203 210 209 203 210 209 203 210 209 203 226 224 218 -75 76 76 15 17 18 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 63 65 64 85 86 85 217 216 210 -211 210 204 210 209 203 210 209 203 210 209 203 211 210 204 217 216 210 -63 65 64 17 19 21 23 25 26 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -186 185 180 186 185 180 186 185 180 186 185 180 186 185 180 186 185 180 -186 185 180 186 185 180 194 194 188 104 105 103 14 16 18 23 25 26 -12 14 15 155 156 152 217 215 209 210 209 203 210 209 203 210 209 203 -212 211 205 208 207 200 51 52 52 18 20 22 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 15 17 19 75 76 76 217 215 209 -210 209 203 210 209 203 210 209 203 210 209 203 217 215 209 123 124 122 -12 14 15 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -14 16 17 75 76 76 213 213 206 211 210 204 210 209 203 210 209 203 -210 209 203 208 207 200 210 209 203 210 209 203 210 209 203 210 209 203 -215 213 207 178 178 173 21 23 24 21 23 24 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 18 22 27 43 33 24 239 160 4 -248 180 4 245 174 5 245 170 5 245 167 3 245 170 5 245 163 4 -245 163 4 244 163 4 244 157 4 251 162 2 254 162 1 119 81 15 -14 22 27 14 20 27 21 23 27 23 25 27 23 25 27 23 25 27 -23 25 27 23 25 27 23 25 27 22 25 27 17 21 27 4 17 28 -57 39 22 198 112 6 252 126 0 239 123 2 238 117 1 237 112 0 -242 147 2 248 180 4 246 172 5 246 172 5 245 167 3 244 167 4 -244 167 4 245 163 4 245 163 4 244 158 4 247 162 2 250 168 2 -198 112 6 46 40 24 10 17 28 18 22 27 22 25 27 23 25 27 -23 25 27 23 25 27 23 25 27 23 25 27 22 25 27 21 23 27 -9 20 28 21 23 27 148 72 11 252 137 0 242 125 0 238 117 1 -238 117 1 238 116 1 236 112 1 237 111 1 237 109 1 235 106 1 -236 103 0 241 105 0 196 92 5 18 22 27 22 25 27 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -31 33 34 189 189 185 214 213 206 210 209 203 210 209 203 210 209 203 -220 219 212 123 124 122 10 13 14 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 14 15 -115 115 113 216 215 208 210 209 203 210 209 203 210 209 203 213 212 206 -194 194 188 31 33 34 21 23 24 0 0 0 13 15 16 104 105 103 -223 222 215 210 209 203 210 209 203 210 209 203 210 209 203 220 219 212 -123 124 122 16 18 19 23 25 26 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 8 10 12 155 156 152 -220 219 212 210 209 203 210 209 203 210 209 203 210 209 203 217 215 209 -186 185 180 21 24 26 20 22 23 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 204 202 197 -0 0 0 5 8 10 5 8 10 5 8 10 5 8 10 5 8 10 -5 8 10 5 8 10 5 8 10 14 16 17 0 0 0 0 0 0 -10 13 14 139 140 136 220 219 212 210 209 203 210 209 203 210 209 203 -210 209 203 216 215 208 85 86 85 15 17 19 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 12 14 15 108 109 107 221 219 213 -210 209 203 210 209 203 210 209 203 211 210 204 217 215 209 85 86 85 -14 16 17 0 0 0 0 0 0 0 0 0 0 0 0 21 23 24 -22 24 25 186 185 180 217 215 209 210 209 203 210 209 203 210 209 203 -216 216 210 155 156 152 204 202 197 211 210 204 210 209 203 210 209 203 -210 209 203 217 216 210 104 105 103 9 12 13 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 27 18 24 27 119 81 15 250 181 3 -245 174 5 246 172 5 245 170 5 245 167 3 245 167 3 244 163 4 -245 163 4 244 158 4 250 168 3 228 138 5 58 46 23 4 17 28 -22 25 27 26 28 30 23 25 27 26 28 30 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 23 25 27 22 25 27 -16 21 27 14 22 27 148 72 11 252 126 0 238 117 1 237 117 0 -248 180 4 245 174 5 246 172 5 246 172 5 245 167 3 244 167 4 -244 167 4 245 163 4 245 163 4 247 162 2 244 163 4 148 89 12 -4 17 28 16 21 27 22 25 27 23 25 27 26 28 30 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 18 24 27 4 17 28 85 50 19 237 117 0 242 125 0 -238 117 1 238 116 1 236 112 1 237 111 1 237 109 1 235 106 1 -236 106 0 236 101 0 249 107 0 85 50 19 17 22 27 23 25 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 24 25 -23 25 26 178 178 173 215 214 208 210 209 203 210 209 203 210 209 203 -217 215 209 155 156 152 9 12 13 23 25 26 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 10 12 -139 140 136 217 215 209 210 209 203 210 209 203 210 209 203 216 215 208 -178 178 173 26 28 30 21 23 24 0 0 0 17 19 21 63 65 64 -224 222 216 210 209 203 210 209 203 210 209 203 210 209 203 215 213 207 -201 200 194 35 37 38 19 21 22 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 12 14 15 14 16 18 -201 200 194 215 213 207 210 209 203 210 209 203 210 209 203 210 209 203 -222 220 214 155 156 152 13 15 17 22 24 25 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -13 15 16 97 97 95 220 219 212 210 209 203 210 209 203 210 209 203 -210 209 203 218 216 210 167 167 162 4 6 8 23 25 26 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 22 24 25 13 15 17 178 178 173 216 215 208 -210 209 203 210 209 203 210 209 203 212 211 205 201 200 194 43 44 44 -19 21 22 0 0 0 0 0 0 0 0 0 23 25 26 5 8 10 -139 140 136 219 218 211 210 209 203 210 209 203 210 209 203 212 211 205 -210 209 203 51 52 52 167 167 162 217 215 209 210 209 203 210 209 203 -210 209 203 212 211 205 219 218 211 30 32 33 19 21 22 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 21 23 27 35 31 25 198 140 8 252 181 4 -248 180 4 246 172 5 245 170 5 245 167 3 245 170 5 245 163 4 -245 163 4 247 162 2 244 158 4 58 46 23 14 22 27 23 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 18 24 27 14 22 27 173 86 8 238 118 0 242 147 2 -248 180 4 245 174 5 245 174 5 246 172 5 245 167 3 244 167 4 -244 167 4 245 163 4 247 162 2 250 164 3 148 89 12 9 20 28 -18 24 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 22 25 27 9 20 28 85 50 19 238 119 0 -238 119 0 238 116 1 236 112 1 237 111 1 237 109 1 235 106 1 -236 106 0 236 101 0 249 107 0 173 86 8 29 29 28 21 23 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -9 12 13 155 156 152 219 218 211 210 209 203 210 209 203 210 209 203 -214 213 207 188 188 182 30 32 32 20 22 24 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 5 8 10 -186 185 180 213 212 206 210 209 203 210 209 203 210 209 203 217 216 210 -155 156 152 21 23 24 22 24 25 0 0 0 22 24 25 14 16 17 -208 207 200 212 211 205 210 209 203 210 209 203 210 209 203 210 209 203 -219 218 211 123 124 122 12 14 15 23 25 26 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 14 16 17 -75 76 76 212 210 204 212 211 205 210 209 203 210 209 203 210 209 203 -211 210 204 217 215 209 108 109 107 8 10 12 23 25 26 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20 22 23 38 39 40 204 202 197 212 211 205 210 209 203 210 209 203 -210 209 203 211 210 204 221 219 213 47 49 49 17 19 21 23 25 26 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 14 16 18 75 76 76 210 209 203 211 210 204 -210 209 203 210 209 203 210 209 203 217 216 210 167 167 162 15 17 19 -21 24 26 0 0 0 0 0 0 23 25 26 17 19 21 51 52 52 -224 222 216 211 210 204 210 209 203 210 209 203 210 209 203 220 219 212 -139 140 136 9 12 13 75 76 76 221 220 213 210 209 203 210 209 203 -210 209 203 210 209 203 220 219 212 139 140 136 19 21 23 22 24 25 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 18 24 27 70 55 22 248 180 4 252 181 4 -245 174 5 246 172 5 245 170 5 245 167 3 245 167 3 244 163 4 -245 163 4 245 167 3 108 69 17 10 17 28 23 25 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 23 25 27 14 22 27 43 33 24 198 112 6 250 164 3 -248 180 4 245 174 5 246 172 5 246 172 5 245 167 3 244 167 4 -245 167 3 243 165 4 254 162 1 198 140 8 26 27 26 18 24 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 22 25 27 14 20 27 108 69 17 -252 126 0 238 116 1 236 112 1 237 111 1 237 109 1 235 106 1 -236 106 0 236 99 0 236 99 0 223 98 1 57 39 22 18 24 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 106 107 104 -13 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 16 17 123 124 122 221 219 213 210 209 203 210 209 203 210 209 203 -211 210 204 212 211 205 75 76 76 13 15 17 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 15 17 19 43 44 44 -221 219 213 210 209 203 210 209 203 210 209 203 210 209 203 222 221 214 -115 115 113 14 16 17 23 25 26 0 0 0 0 0 0 8 10 12 -155 156 152 219 218 211 210 209 203 210 209 203 210 209 203 210 209 203 -212 211 205 211 210 204 75 76 76 5 8 10 21 24 26 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 22 24 25 16 18 19 22 24 25 0 0 0 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 23 25 26 -10 13 14 139 140 136 224 222 216 210 209 203 210 209 203 210 209 203 -210 209 203 212 211 205 219 218 211 43 44 44 15 17 19 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 24 25 19 21 23 155 156 152 219 218 211 210 209 203 210 209 203 -210 209 203 210 209 203 217 216 210 167 167 162 13 15 16 20 22 23 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 19 21 22 9 12 13 191 190 185 214 213 207 210 209 203 -210 209 203 210 209 203 210 209 203 222 220 214 85 86 85 14 16 17 -0 0 0 0 0 0 0 0 0 21 23 24 17 19 21 178 178 173 -217 216 210 210 209 203 210 209 203 210 209 203 211 210 204 223 222 215 -35 37 38 17 19 21 4 6 8 186 185 180 217 215 209 210 209 203 -210 209 203 210 209 203 211 210 204 219 218 211 75 76 76 14 16 17 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 14 20 27 86 62 19 248 180 4 248 180 4 -245 174 5 246 172 5 245 170 5 245 167 3 245 170 5 245 163 4 -250 168 3 178 116 9 9 20 28 4 17 28 16 21 27 18 23 27 -22 25 27 23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 23 25 27 12 18 27 85 50 19 250 168 3 -248 180 4 249 174 4 246 172 5 246 172 5 245 167 3 244 167 4 -244 167 4 247 162 2 250 168 2 43 33 24 16 21 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 21 23 27 18 23 27 14 20 27 4 17 28 4 17 28 -225 114 1 240 113 0 236 112 1 237 111 1 237 109 1 235 106 1 -236 106 0 236 101 0 236 100 0 223 98 1 57 39 22 17 21 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 216 210 104 105 103 -10 13 14 21 23 24 21 23 24 21 23 24 21 23 24 21 23 24 -21 23 24 21 23 24 21 23 24 21 23 24 23 25 26 0 0 0 -17 19 21 75 76 76 219 218 211 210 209 203 210 209 203 210 209 203 -210 209 203 215 213 207 201 200 194 17 19 21 14 16 18 21 23 24 -23 25 26 23 25 26 21 23 24 15 17 19 20 22 24 167 167 162 -219 218 211 210 209 203 210 209 203 210 209 203 210 209 203 226 224 218 -63 65 64 15 17 19 0 0 0 0 0 0 0 0 0 18 20 22 -51 52 52 210 209 203 212 211 205 210 209 203 210 209 203 210 209 203 -210 209 203 212 211 205 227 226 219 97 97 95 8 10 12 16 18 19 -20 22 23 22 24 25 23 25 26 23 25 26 22 24 25 20 22 24 -19 21 22 10 13 14 16 18 19 97 97 95 31 33 34 22 24 25 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 0 0 0 -21 23 24 18 20 22 178 178 173 217 216 210 210 209 203 210 209 203 -210 209 203 210 209 203 217 215 209 189 188 183 34 35 36 19 21 22 -24 26 27 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -1 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 17 19 21 51 52 52 225 224 217 211 210 204 210 209 203 -210 209 203 210 209 203 210 209 203 223 222 215 155 156 152 16 18 19 -14 16 18 21 23 24 22 24 25 23 25 26 22 24 25 20 22 23 -12 14 15 24 26 27 167 167 162 221 219 213 210 209 203 210 209 203 -210 209 203 210 209 203 216 215 208 178 178 173 26 28 30 21 23 24 -0 0 0 0 0 0 23 25 26 9 12 13 123 124 122 221 219 213 -210 209 203 210 209 203 210 209 203 210 209 203 219 218 211 123 124 122 -9 12 13 0 0 0 17 19 21 63 65 64 210 209 203 212 211 205 -210 209 203 210 209 203 210 209 203 216 215 208 188 188 182 23 25 26 -21 23 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 18 24 27 58 46 23 244 172 4 251 178 1 -245 174 5 246 172 5 245 170 5 245 167 3 245 167 3 243 165 4 -250 164 3 238 145 2 178 116 9 153 108 13 86 62 19 35 31 25 -22 25 27 10 17 28 14 20 27 23 25 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 21 23 27 14 20 27 198 140 8 -252 181 4 245 174 5 246 172 5 246 172 5 245 167 3 244 167 4 -245 167 3 250 168 2 178 116 9 4 11 29 23 25 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 22 25 27 14 20 27 -10 17 28 26 27 26 43 33 24 86 62 19 153 108 13 178 116 9 -239 136 1 238 116 1 236 112 1 237 111 1 237 109 1 235 106 1 -236 106 0 236 100 0 236 99 0 223 98 1 43 33 24 21 23 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 216 215 208 108 109 107 -22 24 25 31 33 34 31 33 34 31 33 34 31 33 34 31 33 34 -31 33 34 31 33 34 31 33 34 31 33 34 24 26 27 23 25 26 -20 22 23 30 32 32 186 185 180 214 213 207 210 209 203 210 209 203 -210 209 203 210 209 203 219 218 211 178 178 173 63 65 64 26 28 30 -15 17 18 16 18 19 24 26 27 51 52 52 167 167 162 219 218 211 -210 209 203 210 209 203 210 209 203 210 209 203 214 213 207 194 194 188 -5 8 10 23 25 26 0 0 0 0 0 0 0 0 0 23 25 26 -13 15 17 139 140 136 221 219 213 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 211 210 204 215 214 208 167 167 162 63 65 64 -34 35 36 22 24 25 15 17 19 17 19 21 21 23 24 34 35 36 -43 44 44 115 115 113 188 188 182 222 221 214 43 44 44 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 0 0 0 -23 25 26 17 19 21 51 52 52 219 218 211 212 211 205 210 209 203 -210 209 203 210 209 203 210 209 203 222 220 214 139 140 136 12 14 15 -21 24 26 24 26 27 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 26 5 8 10 155 156 152 218 216 210 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 217 215 209 189 188 183 -63 65 64 30 32 33 20 22 23 14 16 18 21 23 24 31 33 34 -85 86 85 189 188 183 217 215 209 210 209 203 210 209 203 210 209 203 -210 209 203 211 210 204 224 222 216 75 76 76 17 19 21 23 25 26 -0 0 0 0 0 0 19 21 22 51 52 52 204 202 197 213 212 206 -210 209 203 210 209 203 210 209 203 214 213 207 194 194 188 38 39 40 -20 22 23 0 0 0 23 25 26 10 13 14 155 156 152 219 218 211 -210 209 203 210 209 203 210 209 203 210 209 203 219 218 211 123 124 122 -8 10 12 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 22 25 27 26 27 26 198 140 8 252 181 4 -249 174 4 246 172 5 245 170 5 245 167 3 245 170 5 245 163 4 -244 158 4 243 153 2 252 154 1 252 154 1 249 147 1 242 151 2 -178 116 9 148 89 12 86 62 19 4 11 29 4 11 29 10 17 28 -16 21 27 21 23 27 23 25 27 23 25 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 23 25 27 12 18 27 86 62 19 -252 181 4 250 181 3 246 172 5 246 172 5 245 167 3 244 167 4 -250 168 3 250 168 2 86 62 19 14 22 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 23 25 27 23 25 27 -21 23 27 14 20 27 12 18 27 4 11 29 4 17 28 86 62 19 -148 89 12 198 140 8 238 145 2 252 154 1 252 154 1 252 154 1 -243 152 2 237 120 0 236 112 1 237 111 1 237 109 1 235 106 1 -236 106 0 236 101 0 241 105 0 173 86 8 20 22 26 21 23 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 211 210 204 194 194 188 -189 188 183 191 190 184 191 190 184 191 190 184 191 190 184 191 190 184 -191 190 184 191 190 184 191 190 185 199 199 193 75 76 76 17 19 21 -23 25 26 14 16 18 108 109 107 226 224 218 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 216 215 208 221 220 213 191 190 184 -155 156 152 155 156 152 178 178 173 221 219 213 217 215 209 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 221 219 213 104 105 103 -13 15 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -19 21 22 38 39 40 194 194 188 217 215 209 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 211 210 204 217 215 209 226 224 218 -201 200 194 167 167 162 155 156 152 155 156 152 167 167 162 194 194 188 -224 222 216 222 220 214 216 215 208 211 210 204 38 39 40 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 0 0 0 -0 0 0 23 25 26 5 8 10 123 124 122 221 220 213 210 209 203 -210 209 203 210 209 203 210 209 203 211 210 204 218 216 210 97 97 95 -9 12 13 23 25 26 24 26 27 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -1 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 20 22 23 31 33 34 199 199 193 217 216 210 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 215 214 208 -224 222 216 194 194 188 167 167 162 155 156 152 167 167 162 201 200 194 -225 224 217 214 213 207 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 222 221 214 155 156 152 1 3 5 22 24 25 0 0 0 -0 0 0 23 25 26 1 3 5 178 178 173 217 215 209 210 209 203 -210 209 203 210 209 203 210 209 203 222 221 214 115 115 113 9 12 13 -23 25 26 0 0 0 0 0 0 17 19 21 51 52 52 215 213 207 -211 210 204 210 209 203 210 209 203 210 209 203 212 211 205 219 218 211 -31 33 34 18 20 22 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 27 14 22 27 108 69 17 252 181 4 -249 174 4 246 172 5 245 170 5 245 167 3 245 167 3 244 163 4 -243 152 2 242 151 2 242 151 2 243 152 2 243 153 2 246 155 2 -252 154 1 254 162 1 254 162 1 250 164 3 228 138 5 119 81 15 -86 62 19 29 29 28 10 17 28 17 22 27 22 25 27 23 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 4 11 29 -198 140 8 252 181 4 251 178 1 249 174 4 250 168 3 250 168 3 -251 178 1 153 108 13 4 11 29 23 25 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 22 25 27 16 21 27 10 17 28 -35 31 25 86 62 19 119 81 15 242 151 2 254 162 1 254 162 1 -254 162 1 252 154 1 246 155 2 243 152 2 243 152 2 243 152 2 -243 152 2 242 147 2 237 114 1 237 108 0 237 108 0 235 106 1 -236 103 0 236 99 0 249 114 0 69 44 21 17 21 27 23 25 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 210 209 203 212 211 205 -213 212 206 213 212 206 213 212 206 213 212 206 213 212 206 213 212 206 -213 212 206 213 212 206 214 213 207 223 222 215 85 86 85 15 17 19 -0 0 0 22 24 25 10 13 14 194 194 188 217 216 210 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 214 212 206 -217 215 209 217 215 209 215 213 207 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 222 220 214 167 167 162 17 19 21 -22 24 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 15 17 19 38 39 40 213 212 206 217 215 209 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -212 211 205 216 215 208 217 216 210 217 215 209 217 215 209 214 212 206 -210 209 203 210 209 203 211 210 204 211 210 204 43 44 44 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 0 0 0 -0 0 0 0 0 0 22 24 25 16 18 19 167 167 162 219 218 211 -210 209 203 210 209 203 210 209 203 210 209 203 212 211 205 224 222 216 -43 44 44 17 19 21 23 25 26 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 15 17 18 47 49 49 201 200 194 -217 216 210 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 214 212 206 215 213 207 216 215 208 216 215 208 212 211 205 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -224 222 216 155 156 152 14 16 17 22 24 25 0 0 0 0 0 0 -23 25 26 14 16 18 97 97 95 227 226 219 210 209 203 210 209 203 -210 209 203 210 209 203 215 214 208 186 185 180 23 25 26 21 23 24 -0 0 0 0 0 0 0 0 0 23 25 26 16 18 19 123 124 122 -222 220 214 210 209 203 210 209 203 210 209 203 210 209 203 218 216 210 -167 167 162 18 20 22 22 24 25 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 27 35 31 25 198 140 8 -250 168 3 246 172 5 245 170 5 245 167 3 245 163 4 242 153 2 -242 153 2 243 152 2 243 152 2 243 152 2 243 152 2 243 152 2 -243 152 2 243 152 2 243 152 2 243 153 2 246 155 2 254 162 1 -246 155 2 228 138 5 178 116 9 58 46 23 21 23 27 21 23 27 -23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 21 24 26 -17 22 27 119 81 15 228 138 5 245 174 5 244 167 4 198 140 8 -119 81 15 12 18 27 21 23 27 23 25 27 24 26 27 24 26 27 -24 26 27 23 25 27 18 23 27 21 23 27 70 55 22 178 116 9 -238 145 2 251 162 2 254 162 1 246 155 2 243 153 2 243 152 2 -242 151 2 242 151 2 242 151 2 243 152 2 243 152 2 243 152 2 -243 153 2 243 153 2 242 147 2 239 123 2 236 112 1 235 106 1 -237 110 0 246 126 1 198 112 6 14 22 27 22 25 27 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 220 219 212 85 86 85 15 17 19 -0 0 0 0 0 0 16 18 19 63 65 64 194 194 188 218 216 210 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 220 219 212 186 185 180 38 39 40 18 20 22 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 13 15 16 63 65 64 191 190 185 220 219 212 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 211 210 204 212 210 204 38 39 40 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 225 224 217 75 76 76 17 19 21 0 0 0 -0 0 0 0 0 0 0 0 0 16 18 19 51 52 52 208 207 200 -212 211 205 210 209 203 210 209 203 210 209 203 210 209 203 217 215 209 -178 178 173 26 28 30 20 22 23 24 26 27 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -1 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 26 17 19 21 51 52 52 -199 199 193 219 218 211 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 212 211 205 224 222 216 -139 140 136 26 28 30 19 21 22 0 0 0 0 0 0 0 0 0 -18 20 22 43 44 44 201 200 194 213 212 206 210 209 203 210 209 203 -210 209 203 210 209 203 224 222 216 85 86 85 15 17 19 23 25 26 -0 0 0 0 0 0 0 0 0 0 0 0 19 21 22 35 37 38 -216 215 208 212 211 205 210 209 203 210 209 203 210 209 203 211 210 204 -219 218 211 85 86 85 15 17 18 23 25 26 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 14 20 27 70 55 22 -252 154 1 248 161 3 244 158 4 243 157 2 242 153 2 242 153 2 -242 153 2 242 153 2 242 153 2 242 153 2 242 153 2 242 153 2 -242 153 2 242 153 2 242 153 2 242 153 2 242 153 2 242 153 2 -246 155 2 243 157 2 254 162 1 243 153 2 153 108 13 18 22 27 -17 22 27 23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -22 25 27 14 22 27 29 29 28 70 55 22 70 55 22 26 27 26 -12 18 27 22 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 14 20 27 21 23 27 178 116 9 252 154 1 254 162 1 -243 157 2 244 155 3 242 153 2 242 153 2 242 153 2 242 153 2 -242 153 2 242 153 2 242 153 2 242 153 2 242 153 2 242 153 2 -242 153 2 242 153 2 244 155 3 243 157 2 242 147 2 242 147 2 -246 155 2 238 145 2 58 46 23 14 22 27 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 30 32 32 188 188 182 -214 213 207 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 219 218 211 85 86 85 15 17 19 -0 0 0 0 0 0 0 0 0 13 15 16 51 52 52 194 194 188 -226 224 218 214 213 207 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -216 215 208 227 226 219 186 185 180 26 28 30 17 19 21 23 25 26 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 13 15 17 38 39 40 155 156 152 -236 234 227 219 218 211 212 211 205 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 211 210 204 217 215 209 223 222 215 43 44 44 20 22 23 -0 0 0 21 23 24 26 27 26 213 213 206 211 210 204 210 209 203 -210 209 203 210 209 203 227 226 219 75 76 76 16 18 19 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 26 14 16 17 100 100 100 -228 227 220 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -219 218 211 139 140 136 5 8 10 23 25 26 14 16 17 97 97 95 -223 222 215 210 209 203 210 209 203 210 209 203 212 211 205 208 207 200 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 14 16 18 -30 32 33 167 167 162 228 227 220 218 216 210 212 210 204 210 209 203 -210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 210 209 203 -210 209 203 210 209 203 213 212 206 223 222 215 218 216 210 115 115 113 -10 13 14 20 22 23 0 0 0 0 0 0 0 0 0 23 25 26 -8 10 12 155 156 152 221 219 213 210 209 203 210 209 203 210 209 203 -210 209 203 215 214 208 191 190 185 8 10 12 22 24 25 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 10 12 -123 124 122 220 219 212 210 209 203 210 209 203 210 209 203 210 209 203 -217 215 209 191 190 185 29 29 28 20 22 24 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 10 17 28 -86 62 19 242 153 2 251 162 2 244 155 3 244 155 3 244 155 3 -244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 -244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 -244 155 3 244 155 3 244 155 3 246 155 2 254 162 1 228 138 5 -26 27 26 16 21 27 23 25 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 18 24 27 18 24 27 17 21 27 21 23 27 -23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 23 25 27 -12 18 27 58 46 23 228 138 5 254 162 1 244 158 4 244 155 3 -244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 -244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 -244 155 3 244 155 3 244 155 3 244 155 3 244 155 3 254 162 1 -238 145 2 70 55 22 9 20 28 23 25 27 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 23 24 31 33 34 204 202 197 -236 234 227 227 226 219 228 227 220 228 227 220 228 227 220 228 227 220 -228 227 220 228 227 220 228 227 220 228 227 220 228 227 220 228 227 220 -228 227 220 228 227 220 228 227 220 236 234 227 85 86 85 17 19 21 -0 0 0 0 0 0 0 0 0 0 0 0 18 20 22 8 10 12 -115 115 113 189 188 183 226 224 218 222 220 214 217 216 210 215 214 208 -215 214 208 215 214 208 216 215 208 219 218 211 224 222 216 224 222 216 -178 178 173 85 86 85 5 8 10 19 21 23 23 25 26 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 19 21 23 1 3 5 -63 65 64 139 140 136 212 211 205 227 226 219 221 219 213 217 215 209 -215 214 208 215 214 208 215 214 208 215 214 208 217 216 210 220 219 212 -226 224 218 220 219 212 178 178 173 104 105 103 26 28 30 22 24 25 -0 0 0 21 23 24 29 29 28 228 227 220 228 227 220 228 227 220 -228 227 220 228 227 220 236 234 227 85 86 85 16 18 19 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 1 3 5 -167 167 162 228 227 220 228 227 220 228 227 220 228 227 220 228 227 220 -228 227 220 236 234 227 115 115 113 14 16 17 14 16 17 104 105 103 -236 234 227 228 227 220 228 227 220 228 227 220 228 227 220 224 222 216 -4 6 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20 22 23 5 8 10 51 52 52 167 167 162 211 210 204 226 224 218 -219 218 211 217 215 209 215 214 208 215 214 208 215 214 208 217 215 209 -222 220 214 226 224 218 199 199 193 115 115 113 26 28 30 9 12 13 -23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 14 16 18 -108 109 107 236 234 227 228 227 220 228 227 220 228 227 220 228 227 220 -228 227 220 226 224 218 63 65 64 17 19 21 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 22 24 -31 33 34 201 200 194 236 234 227 227 226 219 228 227 220 228 227 220 -228 227 220 236 234 227 167 167 162 9 12 13 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -18 22 27 86 62 19 198 140 8 254 162 1 248 161 3 244 157 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 179 91 1 239 123 2 239 123 2 +239 123 2 239 123 2 239 123 2 239 123 2 239 123 2 239 123 2 +36 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 12 0 +161 88 1 239 123 2 239 123 2 239 123 2 239 123 2 239 123 2 +239 123 2 239 123 2 239 123 2 239 123 2 239 123 2 216 117 2 +70 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +161 88 1 239 123 2 239 123 2 239 123 2 239 123 2 239 123 2 +239 123 2 239 123 2 239 123 2 53 25 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 169 90 1 239 125 2 239 125 2 +239 125 2 239 125 2 239 125 2 239 125 2 239 125 2 239 125 2 +48 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 70 36 0 192 97 1 239 125 2 239 125 2 239 125 2 +239 125 2 239 125 2 239 125 2 216 117 2 113 64 1 10 6 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +179 91 1 239 125 2 239 125 2 239 125 2 239 125 2 239 125 2 +239 125 2 239 125 2 239 125 2 43 21 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 158 78 1 239 125 2 239 125 2 +239 125 2 239 125 2 239 125 2 239 125 2 239 125 2 239 125 2 +57 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 43 21 0 83 40 0 110 51 0 +113 64 1 101 51 0 61 28 0 8 5 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +192 97 1 239 125 2 239 125 2 239 125 2 239 125 2 239 125 2 +239 125 2 239 125 2 239 125 2 26 13 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 119 119 119 153 153 153 204 204 204 204 204 204 153 153 153 +119 119 119 34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 51 51 51 136 136 136 +170 170 170 204 204 204 204 204 204 136 136 136 102 102 102 17 17 17 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 147 76 1 239 126 2 239 126 2 +239 126 2 239 126 2 239 126 2 239 126 2 239 126 2 239 126 2 +79 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +216 117 2 239 126 2 239 126 2 239 126 2 239 126 2 239 126 2 +239 126 2 239 126 2 236 120 1 15 8 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 17 17 17 153 153 153 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 238 238 238 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 51 51 51 187 187 187 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +221 221 221 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 153 153 153 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +68 68 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 34 34 34 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 161 88 1 239 128 2 239 128 2 +239 128 2 239 128 2 239 128 2 239 128 2 239 128 2 239 128 2 +79 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +216 117 2 239 128 2 239 128 2 239 128 2 239 128 2 239 128 2 +239 128 2 239 128 2 239 128 2 26 13 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 102 102 102 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 17 17 17 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 +187 187 187 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 238 238 238 51 51 51 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +221 221 221 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 17 17 17 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 216 117 2 240 130 2 240 130 2 +240 130 2 206 109 2 147 76 1 98 43 0 63 34 1 43 21 0 +8 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +27 17 0 48 27 0 79 40 0 113 64 1 192 97 1 228 121 1 +240 130 2 240 130 2 240 130 2 63 34 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 187 187 187 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 +34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 34 34 34 221 221 221 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 102 102 102 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 86 43 0 240 131 2 179 91 1 102 58 1 +43 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 12 0 +72 43 1 147 76 1 240 130 2 206 109 2 6 4 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +187 187 187 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +221 221 221 17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 17 17 17 221 221 221 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 34 34 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 17 17 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 6 4 0 101 51 0 70 36 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 31 17 0 127 63 1 31 17 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 153 153 153 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 204 204 204 204 204 204 221 221 221 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 187 187 187 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 34 34 +238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 +204 204 204 204 204 204 204 204 204 221 221 221 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 +34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 17 17 17 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 42 29 1 99 64 1 137 86 2 157 99 2 +181 110 2 189 109 2 189 109 2 181 110 2 169 90 1 140 77 1 +102 58 1 48 27 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 22 12 0 91 58 1 +127 80 2 157 99 2 181 110 2 189 109 2 189 109 2 189 109 2 +169 90 1 147 76 1 113 64 1 70 36 0 1 1 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 51 51 51 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 68 68 68 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 102 102 102 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 238 238 238 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 34 34 34 204 204 204 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +187 187 187 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 34 34 34 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 +0 0 0 51 51 51 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 29 1 +127 80 2 187 127 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 206 109 2 140 77 1 48 27 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 6 0 101 70 1 172 112 3 229 147 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 216 117 2 158 78 1 +79 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 51 51 51 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +221 221 221 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 17 17 17 204 204 204 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 17 17 17 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 51 51 51 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 34 34 34 0 0 0 +0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 51 34 1 159 105 3 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 169 90 1 +61 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 12 0 +137 86 2 229 147 3 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 192 97 1 101 51 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 51 51 51 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 221 221 221 221 221 221 68 68 68 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 34 34 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 187 187 187 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +221 221 221 17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 4 2 0 145 97 2 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 147 76 1 22 12 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 101 70 1 229 147 3 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 190 88 0 57 27 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 153 153 153 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 187 187 187 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 34 34 34 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 238 238 238 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 34 34 34 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 136 136 136 +238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +68 68 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +54 36 1 213 144 3 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 117 1 227 107 1 75 35 0 0 0 0 0 0 0 +0 0 0 0 0 0 18 12 0 172 112 3 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 127 63 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 68 68 68 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 99 64 1 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 117 1 238 115 1 237 113 1 118 52 0 0 0 0 +0 0 0 42 29 1 222 154 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +158 78 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +221 221 221 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 116 76 1 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 117 1 238 115 1 237 113 1 237 111 1 98 43 0 +48 27 0 242 175 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 183 82 0 3 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 68 68 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 68 68 68 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 101 70 1 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 117 1 238 115 1 237 114 1 235 99 0 238 118 2 +246 172 5 247 172 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 183 82 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 102 102 102 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 238 238 238 238 238 238 238 238 238 +238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 +238 238 238 238 238 238 187 187 187 0 0 0 0 0 0 0 0 0 +102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 153 153 153 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 73 49 1 246 172 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +242 144 3 241 141 3 241 140 3 241 137 2 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 117 1 238 116 1 236 104 0 237 110 1 247 174 5 +248 181 5 246 166 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 242 142 3 241 140 3 241 138 2 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 159 68 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 8 0 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 243 150 3 242 147 3 242 146 3 +237 141 2 212 134 3 216 117 2 227 136 3 241 135 2 240 134 2 +240 131 2 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 117 1 238 112 1 236 103 0 245 161 5 249 189 6 +246 169 5 246 168 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 243 151 3 +242 148 3 242 146 3 242 144 3 212 134 3 216 117 2 228 121 1 +241 136 2 240 134 2 240 132 2 240 130 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 98 43 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 187 127 3 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 243 153 3 243 152 3 185 119 2 122 79 2 72 43 1 +22 12 0 1 1 0 0 0 0 13 8 0 63 34 1 113 64 1 +179 91 1 240 130 2 239 128 2 239 126 2 239 124 2 239 121 1 +238 119 1 238 118 1 235 101 0 242 139 3 249 189 6 246 172 5 +246 170 5 246 168 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 243 154 3 243 152 3 212 134 3 +137 86 2 81 53 1 31 17 0 4 2 0 0 0 0 8 5 0 +48 27 0 102 58 1 161 88 1 239 128 2 240 128 2 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 102 0 26 13 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 238 238 238 17 17 17 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +73 49 1 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +244 155 4 187 127 3 73 49 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 63 34 1 169 90 1 239 126 2 239 124 2 239 121 1 +238 119 1 237 111 1 239 118 1 247 177 5 248 181 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 244 156 4 229 147 3 113 64 1 1 1 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 31 17 0 147 76 1 239 126 2 +239 124 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 173 76 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 187 187 187 221 221 221 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 +68 68 68 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +153 153 153 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 34 34 34 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 187 187 187 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +222 154 4 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 244 157 4 +137 86 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 102 58 1 239 124 2 239 121 1 +238 120 1 236 104 0 244 150 3 249 189 6 246 173 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 244 158 4 181 110 2 22 12 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 36 0 +216 117 2 239 122 1 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 236 101 0 +53 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 17 17 17 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +204 204 204 0 0 0 34 34 34 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 221 221 221 17 17 17 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 51 51 51 51 51 51 51 51 51 +51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 +51 51 51 51 51 51 34 34 34 0 0 0 0 0 0 0 0 0 +34 34 34 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +187 187 187 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 102 102 102 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 102 102 102 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 49 1 +247 177 5 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 161 4 244 159 4 99 64 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 79 40 0 239 121 1 +237 113 1 239 121 1 247 180 5 248 181 5 247 174 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 165 4 245 163 4 244 161 4 +244 160 4 159 105 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +27 17 0 216 117 2 238 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 236 101 0 +173 76 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 34 34 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 +238 238 238 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 238 238 238 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 +17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 159 114 3 +247 177 5 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 244 160 4 116 76 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 43 0 +236 108 0 242 146 3 249 189 6 247 175 5 247 174 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 165 4 245 163 4 244 161 4 +185 119 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 31 17 0 236 120 1 238 117 1 238 116 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 236 101 0 +231 95 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 34 34 34 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 187 187 187 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 153 153 153 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 17 17 17 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 187 187 187 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 +221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +187 187 187 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 234 169 5 +247 177 5 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 164 4 245 162 4 159 105 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +147 68 0 244 158 4 249 189 6 247 175 5 247 174 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 165 4 245 163 4 241 157 3 +6 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 57 27 0 230 112 1 238 117 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 236 101 0 +231 95 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +153 153 153 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 136 136 136 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 238 238 238 34 34 34 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 153 153 153 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 102 102 102 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 34 34 34 0 0 0 +51 51 51 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 242 175 4 +247 176 5 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 165 4 245 163 4 62 42 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +8 5 0 239 150 3 249 189 6 247 175 5 247 174 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 164 4 245 164 4 99 64 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 4 2 0 192 97 1 237 112 1 237 114 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 236 101 0 +220 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +17 17 17 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 17 17 17 238 238 238 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 17 17 17 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 238 238 238 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 +238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +238 238 238 34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 17 17 17 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 17 17 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 238 238 238 17 17 17 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 187 127 3 +247 180 5 247 175 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 166 4 245 167 4 244 159 4 241 145 3 203 125 2 137 86 2 +91 58 1 42 29 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 127 80 2 249 189 6 247 175 5 247 174 5 246 172 5 +246 170 5 246 168 4 245 167 4 245 167 4 240 155 3 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 26 13 0 72 43 1 +122 79 2 172 112 3 241 157 3 237 141 2 237 111 1 237 113 1 +237 111 1 237 110 1 237 108 1 236 105 1 236 103 0 236 101 0 +231 95 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 221 221 221 17 17 17 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 17 17 204 204 204 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 221 221 221 +17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 238 238 238 68 68 68 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 187 187 187 17 17 17 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 +238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +238 238 238 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 238 238 238 0 0 0 0 0 0 0 0 0 +0 0 0 17 17 17 238 238 238 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 99 64 1 +248 181 5 247 176 5 246 173 5 246 171 5 246 169 4 246 168 4 +245 167 4 245 166 4 243 154 3 243 150 3 243 152 3 243 152 3 +243 152 3 243 152 3 212 134 3 157 99 2 91 58 1 42 29 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 27 17 0 247 177 5 247 180 5 247 174 5 246 172 5 +246 170 5 246 168 4 245 167 4 246 171 4 113 64 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +22 12 0 72 43 1 122 79 2 203 125 2 239 150 3 243 152 3 +243 152 3 243 152 3 243 153 3 244 159 4 240 124 2 236 104 0 +237 112 1 237 110 1 237 108 1 236 105 1 236 104 0 231 95 0 +204 100 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 204 204 204 204 204 204 204 204 204 204 204 204 +204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 +204 204 204 204 204 204 204 204 204 51 51 51 0 0 0 0 0 0 +0 0 0 102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 68 68 68 51 51 51 +51 51 51 153 153 153 238 238 238 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 187 187 187 85 85 85 51 51 51 51 51 51 119 119 119 +221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 238 238 238 17 17 17 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 17 17 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 153 153 153 +68 68 68 51 51 51 51 51 51 119 119 119 221 221 221 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 102 102 102 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 8 0 +245 166 4 248 181 5 247 177 5 246 172 5 246 170 4 246 171 4 +246 169 4 244 158 4 243 150 3 243 152 3 243 152 3 243 152 3 +243 152 3 243 152 3 243 152 3 243 152 3 243 152 3 243 152 3 +212 134 3 157 99 2 91 58 1 35 23 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 81 53 1 247 180 5 247 177 5 246 173 5 +246 171 5 246 172 4 246 172 4 172 112 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 13 8 0 72 43 1 122 79 2 203 125 2 +239 150 3 243 152 3 243 152 3 243 152 3 243 152 3 243 152 3 +243 152 3 243 152 3 243 152 3 244 157 3 243 152 3 238 116 2 +235 101 0 236 105 1 237 105 1 235 99 0 231 95 0 237 105 1 +99 64 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 68 68 68 0 0 0 0 0 0 +0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 +221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 187 187 187 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 238 238 238 17 17 17 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +99 64 1 245 161 5 246 170 5 246 170 5 246 168 4 245 165 4 +244 156 4 243 151 3 243 153 3 243 154 3 243 153 3 243 153 3 +243 153 3 243 153 3 243 153 3 243 153 3 243 153 3 243 153 3 +243 153 3 243 153 3 243 153 3 243 153 3 185 119 2 72 43 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 51 34 1 172 112 3 222 154 4 +233 166 5 195 135 3 101 70 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +31 17 0 137 86 2 229 147 3 243 153 3 243 153 3 243 153 3 +243 153 3 243 153 3 243 153 3 243 153 3 243 153 3 243 153 3 +243 153 3 243 153 3 243 153 3 243 152 3 244 159 4 243 155 3 +240 129 2 237 114 1 237 109 1 237 110 1 239 124 2 212 134 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 68 68 68 0 0 0 0 0 0 +0 0 0 0 0 0 34 34 34 238 238 238 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +34 34 34 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 17 17 221 221 221 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 238 238 238 34 34 34 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 34 34 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 34 34 34 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 181 110 2 243 153 3 243 156 3 243 155 3 243 153 3 +243 153 3 243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 +243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 +243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 +159 105 3 13 8 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 2 0 +13 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 99 64 1 +240 155 3 243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 +243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 243 155 3 +243 155 3 243 155 3 243 155 3 243 155 3 243 154 3 244 158 3 +244 161 3 244 156 4 243 152 3 244 157 3 245 164 4 42 29 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 68 68 68 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 34 34 34 238 238 238 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +238 238 238 68 68 68 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 17 17 17 221 221 221 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 102 102 102 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 221 221 221 17 17 17 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 51 51 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 136 136 136 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 187 127 3 244 155 4 244 155 4 244 156 4 +244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 +244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 +244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 +244 156 4 212 134 3 22 12 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 137 86 2 244 156 4 +244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 +244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 +244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 244 156 4 +244 156 4 244 158 4 245 160 4 244 158 4 62 42 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 68 68 68 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 +17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 136 136 136 238 238 238 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 204 204 204 34 34 34 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +17 17 17 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 238 238 238 68 68 68 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 +17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 221 221 221 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 238 238 238 +17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 157 99 2 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 -244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 251 162 2 -198 140 8 35 31 25 18 23 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 17 22 27 -57 39 22 198 140 8 250 164 3 244 158 4 244 157 4 244 157 4 +244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 +244 157 4 244 157 4 213 144 3 6 4 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 122 79 2 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 -244 157 4 244 157 4 244 157 4 248 161 3 254 162 1 198 140 8 -58 46 23 16 21 27 23 25 27 0 0 0 0 0 0 0 0 0 +244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 244 157 4 +244 157 4 244 157 4 212 134 3 51 34 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 136 136 136 136 136 136 136 136 136 +136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 +136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 +136 136 136 136 136 136 136 136 136 34 34 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +17 17 17 136 136 136 221 221 221 238 238 238 255 255 255 255 255 255 +255 255 255 238 238 238 221 221 221 136 136 136 17 17 17 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 +187 187 187 238 238 238 255 255 255 255 255 255 255 255 255 238 238 238 +221 221 221 153 153 153 34 34 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 +136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 +34 34 34 0 0 0 0 0 0 85 85 85 136 136 136 136 136 136 +136 136 136 136 136 136 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 26 22 25 27 47 48 48 -47 49 49 47 48 48 47 48 48 47 48 48 47 48 48 47 48 48 -47 48 48 47 48 48 47 48 48 47 48 48 47 48 48 47 48 48 -47 48 48 47 48 48 47 49 49 51 52 52 31 33 34 22 24 25 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 24 25 -12 14 15 30 32 32 51 52 52 115 115 113 155 156 152 178 178 173 -178 178 173 178 178 173 167 167 162 155 156 152 97 97 95 47 48 48 -21 23 24 14 16 17 23 25 26 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 17 17 136 136 136 221 221 221 238 238 238 +255 255 255 255 255 255 255 255 255 238 238 238 221 221 221 170 170 170 +51 51 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 51 51 51 136 136 136 +136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 68 68 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -17 19 21 18 20 22 38 39 40 63 65 64 123 124 122 167 167 162 -178 178 173 178 178 173 178 178 173 178 178 173 155 156 152 139 140 136 -75 76 76 43 44 44 24 26 27 12 14 15 22 24 25 0 0 0 -0 0 0 23 25 26 23 25 26 47 49 49 47 49 49 47 48 48 -47 48 48 47 49 49 51 52 52 30 32 32 22 24 25 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 22 24 -30 32 32 47 49 49 47 49 49 47 48 48 47 48 48 47 48 48 -47 49 49 51 52 52 47 48 48 20 22 24 22 24 25 34 35 36 -51 52 52 47 49 49 47 48 48 47 48 48 47 49 49 47 49 49 -19 21 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 26 17 19 21 16 18 19 38 39 40 75 76 76 -139 140 136 167 167 162 178 178 173 178 178 173 178 178 173 167 167 162 -115 115 113 51 52 52 31 33 34 10 13 14 21 23 24 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 24 26 -43 44 44 51 52 52 47 49 49 47 48 48 47 48 48 47 48 48 -47 49 49 47 48 48 24 26 27 23 25 26 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 -19 21 22 38 39 40 47 49 49 47 48 48 47 48 48 47 48 48 -47 48 48 47 49 49 51 52 52 20 22 23 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 51 51 +136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 +68 68 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 25 27 17 21 27 35 31 25 153 108 13 241 156 2 250 168 2 -254 162 1 250 164 3 244 158 4 244 158 4 244 158 4 244 158 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 72 43 1 185 119 2 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 -254 162 1 153 108 13 10 17 28 23 25 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 22 25 27 4 11 29 -178 116 9 250 168 3 248 161 3 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 -244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 248 161 3 -251 162 2 254 162 1 251 178 1 238 145 2 119 81 15 43 33 24 -16 21 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 +244 158 4 244 158 4 244 158 4 159 105 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 23 25 26 20 22 23 -19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 22 19 21 22 19 21 22 22 24 25 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 26 21 23 24 19 21 22 14 16 17 9 12 13 5 8 10 -5 8 10 5 8 10 8 10 12 8 10 12 13 15 16 19 21 22 -22 24 25 23 25 26 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 26 20 22 23 18 20 22 13 15 16 8 10 12 -5 8 10 5 8 10 5 8 10 5 8 10 8 10 12 9 12 13 -14 16 18 19 21 23 22 24 25 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 26 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 22 19 21 22 22 24 25 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -21 23 24 19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 22 20 22 24 0 0 0 0 0 0 22 24 25 -19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 19 21 23 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 22 25 27 20 22 23 16 18 19 -10 13 14 8 10 12 5 8 10 5 8 10 5 8 10 8 10 12 -13 15 16 20 22 23 22 24 25 23 25 26 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -21 23 24 19 21 22 19 21 22 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 23 23 25 26 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -23 25 26 20 22 23 19 21 22 19 21 22 19 21 22 19 21 22 -19 21 22 19 21 22 20 22 23 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 25 27 20 22 26 10 17 28 20 22 26 70 55 22 -153 108 13 198 140 8 250 164 3 250 168 2 254 162 1 248 161 3 -248 161 3 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 +0 0 0 0 0 0 51 34 1 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 -248 161 3 248 161 3 86 62 19 12 18 27 23 25 27 24 26 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 24 26 27 23 25 27 14 22 27 108 69 17 -250 168 2 248 161 3 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 -244 158 4 248 161 3 251 162 2 250 168 2 250 168 2 251 162 2 -178 116 9 153 108 13 58 46 23 14 22 27 13 20 27 21 23 27 -23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 21 23 27 18 22 27 -12 18 27 20 22 26 43 33 24 86 62 19 178 116 9 228 138 5 -239 160 4 250 168 2 250 164 3 247 162 2 247 162 2 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 -244 158 4 250 164 3 198 140 8 21 23 27 21 23 27 23 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 23 25 27 18 22 27 43 33 24 228 138 5 -245 167 3 244 158 4 244 158 4 244 158 4 244 158 4 244 158 4 -244 158 4 244 158 4 244 158 4 247 162 2 248 161 3 250 164 3 -254 162 1 241 156 2 228 138 5 153 108 13 70 55 22 46 40 24 -18 22 27 12 18 27 18 22 27 23 25 27 23 25 27 0 0 0 +213 144 3 122 79 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3253,19 +3105,17 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -23 25 27 23 25 27 18 23 27 9 20 28 4 17 28 9 20 28 -58 46 23 108 69 17 153 108 13 241 156 2 247 162 2 250 168 2 -245 163 4 244 158 4 244 163 4 244 158 4 244 163 4 244 158 4 -244 163 4 248 161 3 250 168 2 119 81 15 14 20 27 23 25 27 -24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 24 26 27 22 25 27 9 20 28 153 108 13 250 168 2 -244 163 4 244 158 4 244 163 4 244 158 4 244 163 4 244 158 4 -244 163 4 250 164 3 250 168 3 241 156 2 239 160 4 153 108 13 -108 69 17 46 40 24 9 20 28 10 17 28 16 21 27 18 23 27 -22 25 27 23 25 27 23 25 27 0 0 0 0 0 0 0 0 0 +42 29 1 122 79 2 172 112 3 229 147 3 244 159 4 244 159 4 +244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 +244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 +244 159 4 244 159 4 244 159 4 244 159 4 72 43 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 213 144 3 244 159 4 244 159 4 244 159 4 +244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 +244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 244 159 4 +244 159 4 244 159 4 240 155 3 203 125 2 145 97 2 73 49 1 +4 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3304,15 +3154,165 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 21 24 26 -18 24 27 13 20 27 10 17 28 4 17 28 35 31 25 119 81 15 -244 163 4 250 164 3 244 163 4 245 163 4 245 163 4 245 163 4 -244 158 4 245 163 4 250 164 3 239 160 4 58 46 23 18 22 27 -23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -24 26 27 23 25 27 13 20 27 86 62 19 245 163 4 247 162 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 8 5 0 51 34 1 127 80 2 +185 119 2 229 147 3 244 160 4 244 160 4 244 160 4 244 160 4 +244 160 4 244 160 4 244 160 4 244 160 4 244 160 4 244 160 4 +244 160 4 244 160 4 244 160 4 244 160 4 213 144 3 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 122 79 2 244 160 4 244 160 4 244 160 4 244 160 4 +244 160 4 244 160 4 244 160 4 244 160 4 244 160 4 244 160 4 +244 160 4 244 160 4 244 160 4 244 160 4 241 157 3 195 135 3 +145 97 2 81 53 1 22 12 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 8 5 0 51 34 1 101 70 1 172 112 3 229 147 3 +244 161 4 244 161 4 244 161 4 244 161 4 244 161 4 244 161 4 +244 161 4 244 161 4 244 161 4 244 161 4 244 161 4 137 86 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +27 17 0 244 161 4 244 161 4 244 161 4 244 161 4 244 161 4 +244 161 4 244 161 4 244 161 4 244 161 4 244 161 4 244 161 4 +242 160 3 202 135 3 128 87 2 73 49 1 27 17 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 6 0 +54 36 1 145 97 2 245 162 4 245 162 4 245 162 4 245 162 4 +245 162 4 245 162 4 245 162 4 245 162 4 245 162 4 245 162 4 +42 29 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +195 135 3 245 162 4 245 162 4 245 162 4 245 162 4 245 162 4 +245 162 4 245 162 4 245 162 4 245 162 4 213 144 3 81 53 1 +27 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 159 105 3 245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 -250 164 3 228 138 5 119 81 15 26 28 30 4 11 29 4 17 28 -9 20 28 18 23 27 22 25 27 22 25 27 0 0 0 0 0 0 +195 135 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 58 1 +245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 +245 163 4 245 163 4 245 163 4 244 161 4 13 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3355,15 +3355,14 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 18 22 27 4 17 28 -119 81 15 250 164 3 245 163 4 244 158 4 245 163 4 245 163 4 -245 163 4 245 163 4 245 163 4 250 168 2 178 116 9 22 25 27 -21 23 27 24 26 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 21 23 27 20 22 26 198 140 8 250 168 3 245 163 4 -245 163 4 245 163 4 244 158 4 245 163 4 245 163 4 247 162 2 -245 167 3 86 62 19 9 20 28 18 23 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 8 5 0 229 155 4 245 165 4 245 165 4 +245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 +245 165 4 99 64 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 8 5 0 243 164 4 +245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 +245 165 4 245 165 4 245 165 4 91 58 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3405,16 +3404,15 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 23 27 -24 26 27 198 140 8 250 168 2 245 163 4 245 163 4 245 163 4 -245 163 4 245 163 4 245 163 4 245 167 3 250 168 2 86 62 19 -14 22 27 23 25 27 24 26 27 24 26 27 24 26 27 24 26 27 -23 25 27 10 17 28 108 69 17 252 181 4 250 164 3 245 163 4 -245 163 4 245 163 4 245 163 4 245 163 4 245 163 4 249 174 4 -178 116 9 22 25 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 91 58 1 245 165 4 245 165 4 +245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 +245 165 4 242 160 3 15 8 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 159 114 3 245 165 4 +245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 245 165 4 +245 165 4 245 165 4 195 135 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3455,17 +3453,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -14 20 27 58 46 23 239 160 4 250 168 3 243 165 4 243 165 4 -243 165 4 243 165 4 245 167 3 245 163 4 250 168 3 249 174 4 -18 22 27 21 23 27 24 26 27 24 26 27 24 26 27 24 26 27 -17 22 27 46 40 24 250 168 2 250 168 3 243 165 4 243 165 4 -243 165 4 243 165 4 243 165 4 243 165 4 250 168 3 239 160 4 -29 29 28 17 22 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 187 127 3 245 166 4 +245 166 4 245 166 4 245 166 4 245 166 4 245 166 4 245 166 4 +245 166 4 245 166 4 172 112 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 54 36 1 245 166 4 245 166 4 +245 166 4 245 166 4 245 166 4 245 166 4 245 166 4 245 166 4 +245 166 4 245 166 4 31 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3506,16 +3503,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 25 27 17 22 27 119 81 15 251 178 1 245 167 3 245 167 3 -244 167 4 244 167 4 244 167 4 244 167 4 245 167 3 251 178 1 -153 108 13 12 18 27 23 25 27 24 26 27 24 26 27 22 25 27 -10 17 28 198 140 8 250 168 2 244 167 4 244 167 4 244 167 4 -244 167 4 244 167 4 244 167 4 245 167 3 250 168 3 119 81 15 -9 20 28 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 27 17 0 246 168 4 +246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 +246 168 4 246 168 4 246 168 4 72 43 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 222 154 4 246 168 4 246 168 4 +246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 +246 168 4 128 87 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3556,16 +3553,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 22 25 27 26 27 26 239 160 4 249 174 4 245 167 3 -245 167 3 245 167 3 245 167 3 245 167 3 244 167 4 250 168 3 -251 178 1 58 46 23 12 18 27 23 25 27 23 25 27 4 17 28 -108 69 17 249 174 4 245 167 3 245 167 3 244 167 4 244 167 4 -245 167 3 245 167 3 245 167 3 251 178 1 198 140 8 24 26 27 -21 23 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 87 2 +246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 +246 168 4 246 168 4 246 168 4 222 154 4 0 0 0 0 0 0 +0 0 0 0 0 0 128 87 2 246 168 4 246 168 4 246 168 4 +246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 246 168 4 +222 154 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3606,16 +3603,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 12 18 27 86 62 19 250 168 3 250 168 3 -245 167 3 245 167 3 245 167 3 245 167 3 245 167 3 245 167 3 -249 174 4 239 160 4 29 29 28 10 17 28 10 17 28 35 31 25 -249 174 4 250 168 3 245 167 3 245 167 3 245 167 3 245 167 3 -245 167 3 245 167 3 250 168 3 245 167 3 58 46 23 17 21 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +222 154 4 246 170 4 246 170 4 246 170 4 246 170 4 246 170 4 +246 170 4 246 170 4 246 170 4 246 170 4 195 135 3 54 36 1 +42 29 1 128 87 2 246 170 4 246 170 4 246 170 4 246 170 4 +246 170 4 246 170 4 246 170 4 246 170 4 246 170 4 246 170 4 +62 42 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3656,16 +3653,15 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 22 25 27 14 22 27 178 116 9 251 178 1 -245 170 5 245 170 5 250 168 3 245 170 5 245 170 5 250 168 3 -245 167 3 251 178 1 198 140 8 119 81 15 119 81 15 228 138 5 -249 174 4 245 170 5 245 170 5 245 170 5 245 170 5 250 168 3 -245 170 5 245 170 5 251 178 1 153 108 13 16 21 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +54 36 1 246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 +246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 +246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 +246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 159 114 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3706,17 +3702,16 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 16 21 27 46 40 24 244 167 4 -249 174 4 245 170 5 245 170 5 245 170 5 245 170 5 245 170 5 -245 170 5 245 170 5 252 181 4 252 181 4 252 181 4 248 180 4 -246 172 5 245 170 5 246 172 5 245 170 5 245 170 5 245 170 5 -245 170 5 249 174 4 245 170 5 12 18 27 18 22 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 159 105 3 246 171 5 246 171 5 246 171 5 246 171 5 +246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 +246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 +246 171 5 246 171 5 246 171 5 246 171 5 246 171 5 4 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3756,11 +3751,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 25 27 9 20 28 108 69 17 -252 181 4 246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 -246 172 5 246 172 5 246 172 5 246 172 5 245 174 5 246 172 5 -246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 -249 174 4 252 181 4 70 55 22 12 18 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3768,6 +3758,10 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 8 5 0 233 166 5 246 173 5 246 173 5 246 173 5 +246 173 5 246 173 5 246 173 5 246 173 5 246 173 5 246 173 5 +246 173 5 246 173 5 246 173 5 246 173 5 246 173 5 246 173 5 +246 173 5 246 173 5 246 173 5 246 173 5 101 70 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3806,11 +3800,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 4 17 28 -198 140 8 252 181 4 246 172 5 246 172 5 246 172 5 246 172 5 -246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 -246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 246 172 5 -252 181 4 153 108 13 21 23 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3819,6 +3808,10 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 81 53 1 247 174 5 247 174 5 247 174 5 +247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 +247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 +247 174 5 247 174 5 247 174 5 202 135 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3856,11 +3849,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 21 27 -58 46 23 252 181 4 251 178 1 245 174 5 246 172 5 245 174 5 -246 172 5 245 174 5 246 172 5 245 174 5 246 172 5 245 174 5 -246 172 5 245 174 5 246 172 5 245 174 5 246 172 5 252 181 4 -244 172 4 46 40 24 18 22 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3870,6 +3858,10 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 159 105 3 247 175 5 247 174 5 +247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 +247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 247 174 5 +247 174 5 247 174 5 242 169 4 22 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3906,11 +3898,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 25 27 -12 18 27 86 62 19 252 181 4 252 181 4 249 174 4 245 174 5 -249 174 4 245 174 5 249 174 4 245 174 5 249 174 4 245 174 5 -249 174 4 245 174 5 249 174 4 249 174 4 252 181 4 251 178 1 -58 46 23 13 20 27 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3921,6 +3908,10 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 159 114 3 247 176 5 +247 176 5 247 176 5 247 176 5 247 176 5 247 176 5 247 176 5 +247 176 5 247 176 5 247 176 5 247 176 5 247 176 5 247 176 5 +247 176 5 233 166 5 42 29 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3957,10 +3948,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 25 27 22 25 27 86 62 19 245 174 5 252 181 4 248 180 4 -248 180 4 245 174 5 248 180 4 245 174 5 248 180 4 245 174 5 -248 180 4 245 174 5 248 180 4 250 181 3 239 160 4 86 62 19 -10 17 28 23 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -3971,6 +3958,10 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 87 2 +247 177 5 247 177 5 247 177 5 247 177 5 247 177 5 247 177 5 +247 177 5 247 177 5 247 177 5 247 177 5 247 177 5 247 177 5 +187 127 3 35 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -4007,10 +3998,29 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 22 25 27 13 20 27 70 55 22 198 140 8 252 181 4 -252 181 4 252 181 4 252 181 4 248 180 4 251 178 1 252 181 4 -252 181 4 252 181 4 252 181 4 198 140 8 46 40 24 14 22 27 -24 26 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +51 34 1 159 114 3 233 166 5 234 169 5 234 169 5 234 169 5 +234 169 5 234 169 5 234 169 5 234 169 5 195 135 3 99 64 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -4057,9 +4067,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 23 25 27 14 22 27 9 20 28 86 62 19 -153 108 13 198 140 8 239 160 4 239 160 4 244 172 4 239 160 4 -198 140 8 153 108 13 70 55 22 4 17 28 18 24 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -4107,9 +4114,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 14 22 27 -24 26 27 35 31 25 58 46 23 70 55 22 58 46 23 46 40 24 -30 32 32 18 24 27 14 22 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -4157,9 +4161,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 25 27 -24 26 27 18 24 27 14 22 27 14 22 27 18 24 27 18 24 27 -22 25 27 22 25 27 22 25 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -4208,7 +4209,6 @@ P3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 1 3 5 0 0 0 1 3 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/sysdrv/source/uboot/rkbin/bin/rv11/rv1106_spl_v1.01.bin b/sysdrv/source/uboot/rkbin/bin/rv11/rv1106_spl_v1.01.bin index bab9bf9bb..5d34f4133 100644 Binary files a/sysdrv/source/uboot/rkbin/bin/rv11/rv1106_spl_v1.01.bin and b/sysdrv/source/uboot/rkbin/bin/rv11/rv1106_spl_v1.01.bin differ diff --git a/sysdrv/source/uboot/u-boot/drivers/mmc/mmc.c b/sysdrv/source/uboot/u-boot/drivers/mmc/mmc.c index 7a50fe863..9edb444d0 100644 --- a/sysdrv/source/uboot/u-boot/drivers/mmc/mmc.c +++ b/sysdrv/source/uboot/u-boot/drivers/mmc/mmc.c @@ -2275,6 +2275,11 @@ int mmc_start_init(struct mmc *mmc) /* Test for SD version 2 */ err = mmc_send_if_cond(mmc); + if(err){ + mmc_go_idle(mmc); + mmc_get_blk_desc(mmc)->hwpart = 0; + mmc_send_if_cond(mmc); + } /* Now try to get the SD card's operating condition */ err = sd_send_op_cond(mmc); diff --git a/sysdrv/tools/board/android-tools/S50usbdevice b/sysdrv/tools/board/android-tools/S50usbdevice index d29c2334b..be39abcab 100755 --- a/sysdrv/tools/board/android-tools/S50usbdevice +++ b/sysdrv/tools/board/android-tools/S50usbdevice @@ -30,7 +30,7 @@ USB_CONFIGS_DIR=${USB_CONFIGFS_DIR}/configs/${USB_SKELETON} # For VBUS_ALWAYS_ON usb otg is not support ums # Since the block to ums is always occupated by USB due to no disconneted state UMS_BLOCK=/userdata/ums_shared.img -UMS_BLOCK_SIZE=0 #unit M +UMS_BLOCK_SIZE=0 #unit M UMS_BLOCK_TYPE=fat UMS_BLOCK_AUTO_MOUNT=off UMS_RO=0 @@ -42,13 +42,11 @@ UVC_U_DIR=${UVC_STREAMING_DIR}/uncompressed/u/ UVC_M_DIR=${UVC_STREAMING_DIR}/mjpeg/m/ UVC_F_DIR=${UVC_STREAMING_DIR}/framebased/f/ -test_write() -{ - test -e $2 && echo $1 > $2 +test_write() { + test -e $2 && echo $1 >$2 } -function_init() -{ +function_init() { mkdir ${USB_FUNCTIONS_DIR}/uac1.gs0 test_write 1 ${USB_FUNCTIONS_DIR}/uac1.gs0/c_feature_unit test_write 1 ${USB_FUNCTIONS_DIR}/uac1.gs0/p_feature_unit @@ -66,38 +64,36 @@ function_init() mkdir ${USB_FUNCTIONS_DIR}/hid.usb0 } -configfs_init() -{ +configfs_init() { echo "Debug: configfs_init" mkdir /dev/usb-ffs mount -t configfs none ${CONFIGFS_DIR} mkdir ${USB_CONFIGFS_DIR} -m 0770 - echo 0x2207 > ${USB_CONFIGFS_DIR}/idVendor - echo 0x0310 > ${USB_CONFIGFS_DIR}/bcdDevice - echo 0x0200 > ${USB_CONFIGFS_DIR}/bcdUSB - mkdir ${USB_STRINGS_DIR} -m 0770 - SERIAL=`cat /proc/cpuinfo | grep Serial | awk '{print $3}'` - if [ -z $SERIAL ];then + echo 0x2207 >${USB_CONFIGFS_DIR}/idVendor + echo 0x0310 >${USB_CONFIGFS_DIR}/bcdDevice + echo 0x0200 >${USB_CONFIGFS_DIR}/bcdUSB + mkdir ${USB_STRINGS_DIR} -m 0770 + SERIAL=$(cat /proc/cpuinfo | grep Serial | awk '{print $3}') + if [ -z $SERIAL ]; then SERIAL=0123456789ABCDEF fi - echo $SERIAL > ${USB_STRINGS_DIR}/serialnumber - echo "rockchip" > ${USB_STRINGS_DIR}/manufacturer - echo "rk3xxx" > ${USB_STRINGS_DIR}/product + echo $SERIAL >${USB_STRINGS_DIR}/serialnumber + echo "rockchip" >${USB_STRINGS_DIR}/manufacturer + echo "rk3xxx" >${USB_STRINGS_DIR}/product function_init - mkdir ${USB_CONFIGS_DIR} -m 0770 - mkdir ${USB_CONFIGS_DIR}/strings/${USB_ATTRIBUTE} -m 0770 + mkdir ${USB_CONFIGS_DIR} -m 0770 + mkdir ${USB_CONFIGS_DIR}/strings/${USB_ATTRIBUTE} -m 0770 - echo 0x1 > ${USB_CONFIGFS_DIR}/os_desc/b_vendor_code - echo "MSFT100" > ${USB_CONFIGFS_DIR}/os_desc/qw_sign - echo 500 > ${USB_CONFIGS_DIR}/MaxPower + echo 0x1 >${USB_CONFIGFS_DIR}/os_desc/b_vendor_code + echo "MSFT100" >${USB_CONFIGFS_DIR}/os_desc/qw_sign + echo 500 >${USB_CONFIGS_DIR}/MaxPower ln -s ${USB_CONFIGS_DIR} ${USB_CONFIGFS_DIR}/os_desc/b.1 } -make_config_string() -{ +make_config_string() { tmp=$CONFIG_STRING if [ -n "$CONFIG_STRING" ]; then CONFIG_STRING=${tmp}_${1} @@ -106,131 +102,127 @@ make_config_string() fi } -parse_parameter() -{ +parse_parameter() { # find name and var - NAME=`echo $1 | awk -F "=" '{print $1}'` - VAR=`echo $1 | awk -F "=" '{print $2}'` + NAME=$(echo $1 | awk -F "=" '{print $1}') + VAR=$(echo $1 | awk -F "=" '{print $2}') case "$NAME" in - ums_block) - UMS_BLOCK=${VAR} - ;; - ums_block_size) - if [ ! "$VAR" -gt 0 ] 2>/dev/null ;then - echo "$VAR is not a number" - exit 1 - fi - UMS_BLOCK_SIZE=${VAR} - ;; - ums_block_type) - UMS_BLOCK_TYPE=${VAR} - ;; - ums_block_auto_mount) - UMS_BLOCK_AUTO_MOUNT=${VAR} - ;; - ums_ro) - if [ "$VAR" != "off" ]; then - echo "Set UMS read-only" - UMS_RO=1 - fi - UMS_RO=0 - ;; + ums_block) + UMS_BLOCK=${VAR} + ;; + ums_block_size) + if [ ! "$VAR" -gt 0 ] 2>/dev/null; then + echo "$VAR is not a number" + exit 1 + fi + UMS_BLOCK_SIZE=${VAR} + ;; + ums_block_type) + UMS_BLOCK_TYPE=${VAR} + ;; + ums_block_auto_mount) + UMS_BLOCK_AUTO_MOUNT=${VAR} + ;; + ums_ro) + if [ "$VAR" != "off" ]; then + echo "Set UMS read-only" + UMS_RO=1 + fi + UMS_RO=0 + ;; esac } -parameter_init() -{ - while read line - do +parameter_init() { + while read line; do case "$line" in - usb_mtp_en) - MTP_EN=on - make_config_string mtp - ;; - usb_adb_en) - ADB_EN=on - make_config_string adb - ;; - usb_ums_en) - UMS_EN=on - make_config_string ums - ;; - usb_ntb_en) - NTB_EN=on - make_config_string ntb - ;; - usb_acm_en) - ACM_EN=on - make_config_string acm - ;; - usb_uac1_en) - UAC1_EN=on - make_config_string uac1 - ;; - usb_uac2_en) - UAC2_EN=on - make_config_string uac2 - ;; - usb_uvc_en) - UVC_EN=on - make_config_string uvc - ;; - usb_rndis_en) - RNDIS_EN=on - make_config_string rndis - ;; - usb_hid_en) - HID_EN=on - make_config_string hid - ;; - *) - parse_parameter ${line} - ;; - esac - done < $USB_CONFIG_FILE - - case "$CONFIG_STRING" in - ums) - PID=0x0000 + usb_mtp_en) + MTP_EN=on + make_config_string mtp ;; - mtp) - PID=0x0001 + usb_adb_en) + ADB_EN=on + make_config_string adb ;; - adb) - PID=0x0006 + usb_ums_en) + UMS_EN=on + make_config_string ums ;; - mtp_adb | adb_mtp) - PID=0x0011 + usb_ntb_en) + NTB_EN=on + make_config_string ntb ;; - ums_adb | adb_ums) - PID=0x0018 + usb_acm_en) + ACM_EN=on + make_config_string acm ;; - acm) - PID=0x1005 + usb_uac1_en) + UAC1_EN=on + make_config_string uac1 + ;; + usb_uac2_en) + UAC2_EN=on + make_config_string uac2 + ;; + usb_uvc_en) + UVC_EN=on + make_config_string uvc + ;; + usb_rndis_en) + RNDIS_EN=on + make_config_string rndis + ;; + usb_hid_en) + HID_EN=on + make_config_string hid ;; *) - PID=0x0019 + parse_parameter ${line} + ;; + esac + done <$USB_CONFIG_FILE + + case "$CONFIG_STRING" in + ums) + PID=0x0000 + ;; + mtp) + PID=0x0001 + ;; + adb) + PID=0x0006 + ;; + mtp_adb | adb_mtp) + PID=0x0011 + ;; + ums_adb | adb_ums) + PID=0x0018 + ;; + acm) + PID=0x1005 + ;; + *) + PID=0x0019 + ;; esac } -use_os_desc() -{ - if [ $MTP_EN = on ];then - echo "MTP" > ${USB_FUNCTIONS_DIR}/mtp.gs0/os_desc/interface.MTP/compatible_id - echo 1 > ${USB_CONFIGFS_DIR}/os_desc/use +use_os_desc() { + if [ $MTP_EN = on ]; then + echo "MTP" >${USB_FUNCTIONS_DIR}/mtp.gs0/os_desc/interface.MTP/compatible_id + echo 1 >${USB_CONFIGFS_DIR}/os_desc/use fi } -pre_run_binary() -{ - if [ $ADB_EN = on ];then +pre_run_binary() { + if [ $ADB_EN = on ]; then mkdir /dev/usb-ffs/adb -m 0770 mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb start-stop-daemon --start --quiet --background --exec /usr/bin/adbd fi - if [ $NTB_EN = on ];then + if [ $NTB_EN = on ]; then mkdir /dev/usb-ffs/ntb -m 0770 mount -o uid=2000,gid=2000 -t functionfs ntb /dev/usb-ffs/ntb # Not start app here @@ -239,65 +231,60 @@ pre_run_binary() # Add uvc app here with start-stop-daemon } -configure_uvc_resolution_yuyv() -{ +configure_uvc_resolution_yuyv() { W=$1 H=$2 DIR=${UVC_U_DIR}/${H}p/ mkdir ${DIR} - echo $W > ${DIR}/wWidth - echo $H > ${DIR}/wHeight - echo 333333 > ${DIR}/dwDefaultFrameInterval - echo $((W*H*20)) > ${DIR}/dwMinBitRate - echo $((W*H*20)) > ${DIR}/dwMaxBitRate - echo $((W*H*2)) > ${DIR}/dwMaxVideoFrameBufferSize - echo -e "333333\n666666\n1000000\n2000000" > ${DIR}/dwFrameInterval + echo $W >${DIR}/wWidth + echo $H >${DIR}/wHeight + echo 333333 >${DIR}/dwDefaultFrameInterval + echo $((W * H * 20)) >${DIR}/dwMinBitRate + echo $((W * H * 20)) >${DIR}/dwMaxBitRate + echo $((W * H * 2)) >${DIR}/dwMaxVideoFrameBufferSize + echo -e "333333\n666666\n1000000\n2000000" >${DIR}/dwFrameInterval } -configure_uvc_resolution_mjpeg() -{ +configure_uvc_resolution_mjpeg() { W=$1 H=$2 DIR=${UVC_M_DIR}/${H}p/ mkdir ${DIR} - echo $W > ${DIR}/wWidth - echo $H > ${DIR}/wHeight - echo 333333 > ${DIR}/dwDefaultFrameInterval - echo $((W*H*20)) > ${DIR}/dwMinBitRate - echo $((W*H*20)) > ${DIR}/dwMaxBitRate - echo $((W*H*2)) > ${DIR}/dwMaxVideoFrameBufferSize - echo -e "333333\n666666\n1000000\n2000000" > ${DIR}/dwFrameInterval + echo $W >${DIR}/wWidth + echo $H >${DIR}/wHeight + echo 333333 >${DIR}/dwDefaultFrameInterval + echo $((W * H * 20)) >${DIR}/dwMinBitRate + echo $((W * H * 20)) >${DIR}/dwMaxBitRate + echo $((W * H * 2)) >${DIR}/dwMaxVideoFrameBufferSize + echo -e "333333\n666666\n1000000\n2000000" >${DIR}/dwFrameInterval } -configure_uvc_resolution_h264() -{ +configure_uvc_resolution_h264() { W=$1 H=$2 DIR=${UVC_F_DIR}/${H}p/ mkdir ${DIR} - echo $W > ${DIR}/wWidth - echo $H > ${DIR}/wHeight - echo 333333 > ${DIR}/dwDefaultFrameInterval - echo $((W*H*10)) > ${DIR}/dwMinBitRate - echo $((W*H*10)) > ${DIR}/dwMaxBitRate + echo $W >${DIR}/wWidth + echo $H >${DIR}/wHeight + echo 333333 >${DIR}/dwDefaultFrameInterval + echo $((W * H * 10)) >${DIR}/dwMinBitRate + echo $((W * H * 10)) >${DIR}/dwMaxBitRate #echo $((W*H*2)) > ${DIR}/dwMaxVideoFrameBufferSize - echo -e "333333\n666666\n1000000\n2000000" > ${DIR}/dwFrameInterval + echo -e "333333\n666666\n1000000\n2000000" >${DIR}/dwFrameInterval } -syslink_function() -{ +syslink_function() { ln -s ${USB_FUNCTIONS_DIR}/$1 ${USB_CONFIGS_DIR}/f${USB_FUNCTIONS_CNT} let USB_FUNCTIONS_CNT=USB_FUNCTIONS_CNT+1 } -bind_functions() -{ +bind_functions() { USB_FUNCTIONS_CNT=1 test $UAC1_EN = on && syslink_function uac1.gs0 test $UAC2_EN = on && syslink_function uac2.gs0 - if [ $UVC_EN = on ];then + if [ $UVC_EN = on ]; then #echo 3072 > ${UVC_DIR}/streaming_maxpacket #echo 1 > ${UVC_DIR}/streaming_bulk @@ -342,55 +329,52 @@ bind_functions() test $ACM_EN = on && syslink_function acm.gs6 if [ $HID_EN = on ]; then - echo 1 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/protocol - echo 1 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/subclass - echo 8 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/report_length - echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/report_desc + echo 1 >/sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/protocol + echo 1 >/sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/subclass + echo 8 >/sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/report_length + echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 >/sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/report_desc syslink_function hid.usb0 fi - if [ $UMS_EN = on ];then - echo ${UMS_RO} > ${USB_FUNCTIONS_DIR}/mass_storage.0/lun.0/ro + if [ $UMS_EN = on ]; then + echo ${UMS_RO} >${USB_FUNCTIONS_DIR}/mass_storage.0/lun.0/ro if [ "$UMS_BLOCK_SIZE" != "0" -a ! -e ${UMS_BLOCK} ]; then dd if=/dev/zero of=${UMS_BLOCK} bs=1M count=${UMS_BLOCK_SIZE} mkfs.${UMS_BLOCK_TYPE} ${UMS_BLOCK} test $? && echo "Warning: failed to mkfs.${UMS_BLOCK_TYPE} ${UMS_BLOCK}" fi mkdir /mnt/ums -p - if [ $UMS_BLOCK_AUTO_MOUNT = on ];then + if [ $UMS_BLOCK_AUTO_MOUNT = on ]; then mount ${UMS_BLOCK} /mnt/ums else - echo ${UMS_BLOCK} > ${USB_FUNCTIONS_DIR}/mass_storage.0/lun.0/file + echo ${UMS_BLOCK} >${USB_FUNCTIONS_DIR}/mass_storage.0/lun.0/file fi syslink_function mass_storage.0 fi - echo ${CONFIG_STRING} > ${USB_CONFIGS_DIR}/strings/${USB_ATTRIBUTE}/configuration + echo ${CONFIG_STRING} >${USB_CONFIGS_DIR}/strings/${USB_ATTRIBUTE}/configuration } -run_binary() -{ - if [ $MTP_EN = on ];then +run_binary() { + if [ $MTP_EN = on ]; then start-stop-daemon --start --quiet --background --exec /usr/bin/mtp-server fi - if [ $RNDIS_EN = on ];then + if [ $RNDIS_EN = on ]; then - sleep .5 - ifconfig usb0 172.32.0.70 - ifconfig usb0 up + sleep .5 + ifconfig usb0 172.32.0.70 + ifconfig usb0 up fi } -program_kill() -{ - P_PID=`ps | grep $1 | grep -v grep | awk '{print $1}'` +program_kill() { + P_PID=$(ps | grep $1 | grep -v grep | awk '{print $1}') test -z ${P_PID} || kill -9 ${P_PID} } -usb_device_stop() -{ - echo "none" > ${USB_CONFIGFS_DIR}/UDC +usb_device_stop() { + echo "none" >${USB_CONFIGFS_DIR}/UDC program_kill adbd program_kill mtp-server ls ${USB_CONFIGS_DIR} | grep f[0-9] | xargs -I {} rm ${USB_CONFIGS_DIR}/{} @@ -399,38 +383,38 @@ usb_device_stop() case "$1" in start) ifconfig lo up -# if [ ! -e "/tmp/.usb_config" ]; then -# echo "$0: Cannot find .usb_config" -# # exit 0 -# USB_CONFIG_FILE=/tmp/.usb_config -# echo "usb_adb_en" >> $USB_CONFIG_FILE -# fi + # if [ ! -e "/tmp/.usb_config" ]; then + # echo "$0: Cannot find .usb_config" + # # exit 0 + # USB_CONFIG_FILE=/tmp/.usb_config + # echo "usb_adb_en" >> $USB_CONFIG_FILE + # fi -# if [ -e /tmp/.usb_config ]; then -# USB_CONFIG_FILE=/tmp/.usb_config -# fi + # if [ -e /tmp/.usb_config ]; then + # USB_CONFIG_FILE=/tmp/.usb_config + # fi parameter_init -# if [ -z $CONFIG_STRING ]; then -# echo "$0: no function be selected" -# exit 0 -# fi + # if [ -z $CONFIG_STRING ]; then + # echo "$0: no function be selected" + # exit 0 + # fi test -d ${USB_CONFIGFS_DIR} || configfs_init use_os_desc - echo $PID > ${USB_CONFIGFS_DIR}/idProduct + echo $PID >${USB_CONFIGFS_DIR}/idProduct bind_functions pre_run_binary sleep 1 - UDC=`ls /sys/class/udc/| awk '{print $1}'` - echo $UDC > ${USB_CONFIGFS_DIR}/UDC + UDC=$(ls /sys/class/udc/ | awk '{print $1}') + echo $UDC >${USB_CONFIGFS_DIR}/UDC run_binary ;; stop) usb_device_stop ;; -restart|reload) +restart | reload) # Do restart usb by udev - echo "USB_FORCE_CHANGED" >> /tmp/.usb_config + echo "USB_FORCE_CHANGED" >>/tmp/.usb_config usb_device_stop sleep 1 $0 start @@ -440,6 +424,7 @@ restart|reload) *) echo "Usage: $0 {start|stop|restart}" exit 1 + ;; esac exit 0 diff --git a/sysdrv/tools/board/android-tools/S90usb0config b/sysdrv/tools/board/android-tools/S99usb0config similarity index 100% rename from sysdrv/tools/board/android-tools/S90usb0config rename to sysdrv/tools/board/android-tools/S99usb0config diff --git a/sysdrv/tools/board/buildroot/S99hciinit b/sysdrv/tools/board/buildroot/S99hciinit index d747f0c87..2b2f67a06 100755 --- a/sysdrv/tools/board/buildroot/S99hciinit +++ b/sysdrv/tools/board/buildroot/S99hciinit @@ -3,7 +3,7 @@ check_hciconfig() { if command -v hciattach &> /dev/null; then if lsmod | grep -q "aic8800_fdrv"; then - hciattach -s 115200 /dev/ttyS1 any 115200 flow nosleep& + hciattach -s 1500000 /dev/ttyS1 any 1500000 flow nosleep& sleep 2 if hciconfig -a | grep -q "hci0"; then hciconfig hci0 up& diff --git a/sysdrv/tools/board/buildroot/busybox.config b/sysdrv/tools/board/buildroot/busybox.config index 3cae292c6..dca54501c 100755 --- a/sysdrv/tools/board/buildroot/busybox.config +++ b/sysdrv/tools/board/buildroot/busybox.config @@ -835,7 +835,7 @@ CONFIG_MT=y CONFIG_PARTPROBE=y # CONFIG_RAIDAUTORUN is not set # CONFIG_READAHEAD is not set -# CONFIG_RFKILL is not set +CONFIG_RFKILL=y CONFIG_RUNLEVEL=y # CONFIG_RX is not set CONFIG_SEEDRNG=y diff --git a/sysdrv/tools/board/emmc/emmc_wifi_bt_init.sh b/sysdrv/tools/board/emmc/emmc_wifi_bt_init.sh index f9a760563..03342dabc 100755 --- a/sysdrv/tools/board/emmc/emmc_wifi_bt_init.sh +++ b/sysdrv/tools/board/emmc/emmc_wifi_bt_init.sh @@ -2,10 +2,19 @@ if [ "$(cat /proc/device-tree/model)" == "Luckfox Pico Ultra W" ]; then systemctl stop wpa_supplicant - if [ -d /usr/ko ]; then - cd /usr/ko + if [ -d /oem/usr/ko ]; then + cd /oem/usr/ko if [ -z "$(ifconfig | grep "wlan0")" ]; then - ./insmod_wifi.sh + insmod cfg80211.ko + insmod libarc4.ko + insmod ctr.ko + insmod ccm.ko + insmod aes_generic.ko + insmod aic8800_bsp.ko + sleep 0.2 + insmod aic8800_fdrv.ko + sleep 2 + insmod aic8800_btplm.ko else # wait systemctl sleep 0.5 diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_bsp.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_bsp.ko deleted file mode 100644 index 0b697e0ce..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_bsp.ko and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_btlpm.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_btlpm.ko deleted file mode 100644 index 4771c4cc1..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_btlpm.ko and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_fdrv.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_fdrv.ko deleted file mode 100644 index 0a256e5a0..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800_fdrv.ko and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/aic_userconfig_8800dc.txt b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/aic_userconfig_8800dc.txt deleted file mode 100755 index d42ca2427..000000000 --- a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/aic_userconfig_8800dc.txt +++ /dev/null @@ -1,56 +0,0 @@ -# AIC USERCONFIG 2022/0803/1707 - -# txpwr_lvl -enable=1 -lvl_11b_11ag_1m_2g4=20 -lvl_11b_11ag_2m_2g4=20 -lvl_11b_11ag_5m5_2g4=20 -lvl_11b_11ag_11m_2g4=20 -lvl_11b_11ag_6m_2g4=20 -lvl_11b_11ag_9m_2g4=20 -lvl_11b_11ag_12m_2g4=20 -lvl_11b_11ag_18m_2g4=20 -lvl_11b_11ag_24m_2g4=18 -lvl_11b_11ag_36m_2g4=18 -lvl_11b_11ag_48m_2g4=16 -lvl_11b_11ag_54m_2g4=16 -lvl_11n_11ac_mcs0_2g4=20 -lvl_11n_11ac_mcs1_2g4=20 -lvl_11n_11ac_mcs2_2g4=20 -lvl_11n_11ac_mcs3_2g4=20 -lvl_11n_11ac_mcs4_2g4=18 -lvl_11n_11ac_mcs5_2g4=18 -lvl_11n_11ac_mcs6_2g4=16 -lvl_11n_11ac_mcs7_2g4=16 -lvl_11n_11ac_mcs8_2g4=16 -lvl_11n_11ac_mcs9_2g4=16 -lvl_11ax_mcs0_2g4=20 -lvl_11ax_mcs1_2g4=20 -lvl_11ax_mcs2_2g4=20 -lvl_11ax_mcs3_2g4=20 -lvl_11ax_mcs4_2g4=18 -lvl_11ax_mcs5_2g4=18 -lvl_11ax_mcs6_2g4=16 -lvl_11ax_mcs7_2g4=16 -lvl_11ax_mcs8_2g4=16 -lvl_11ax_mcs9_2g4=16 -lvl_11ax_mcs10_2g4=15 -lvl_11ax_mcs11_2g4=15 - -# txpwr_ofst -ofst_enable=0 -ofst_chan_1_4=0 -ofst_chan_5_9=0 -ofst_chan_10_13=0 -ofst_chan_36_64=0 -ofst_chan_100_120=0 -ofst_chan_122_140=0 -ofst_chan_142_165=0 - -# xtal cap -xtal_enable=0 -xtal_cap=24 -xtal_cap_fine=31 - - - diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/aic_userconfig_8800dw.txt b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/aic_userconfig_8800dw.txt deleted file mode 100755 index d42ca2427..000000000 --- a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/aic_userconfig_8800dw.txt +++ /dev/null @@ -1,56 +0,0 @@ -# AIC USERCONFIG 2022/0803/1707 - -# txpwr_lvl -enable=1 -lvl_11b_11ag_1m_2g4=20 -lvl_11b_11ag_2m_2g4=20 -lvl_11b_11ag_5m5_2g4=20 -lvl_11b_11ag_11m_2g4=20 -lvl_11b_11ag_6m_2g4=20 -lvl_11b_11ag_9m_2g4=20 -lvl_11b_11ag_12m_2g4=20 -lvl_11b_11ag_18m_2g4=20 -lvl_11b_11ag_24m_2g4=18 -lvl_11b_11ag_36m_2g4=18 -lvl_11b_11ag_48m_2g4=16 -lvl_11b_11ag_54m_2g4=16 -lvl_11n_11ac_mcs0_2g4=20 -lvl_11n_11ac_mcs1_2g4=20 -lvl_11n_11ac_mcs2_2g4=20 -lvl_11n_11ac_mcs3_2g4=20 -lvl_11n_11ac_mcs4_2g4=18 -lvl_11n_11ac_mcs5_2g4=18 -lvl_11n_11ac_mcs6_2g4=16 -lvl_11n_11ac_mcs7_2g4=16 -lvl_11n_11ac_mcs8_2g4=16 -lvl_11n_11ac_mcs9_2g4=16 -lvl_11ax_mcs0_2g4=20 -lvl_11ax_mcs1_2g4=20 -lvl_11ax_mcs2_2g4=20 -lvl_11ax_mcs3_2g4=20 -lvl_11ax_mcs4_2g4=18 -lvl_11ax_mcs5_2g4=18 -lvl_11ax_mcs6_2g4=16 -lvl_11ax_mcs7_2g4=16 -lvl_11ax_mcs8_2g4=16 -lvl_11ax_mcs9_2g4=16 -lvl_11ax_mcs10_2g4=15 -lvl_11ax_mcs11_2g4=15 - -# txpwr_ofst -ofst_enable=0 -ofst_chan_1_4=0 -ofst_chan_5_9=0 -ofst_chan_10_13=0 -ofst_chan_36_64=0 -ofst_chan_100_120=0 -ofst_chan_122_140=0 -ofst_chan_142_165=0 - -# xtal cap -xtal_enable=0 -xtal_cap=24 -xtal_cap_fine=31 - - - diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin deleted file mode 100755 index bc175da27..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_calib_8800dc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin deleted file mode 100755 index 7615a823d..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_h_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_ipc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_ipc_u02.bin deleted file mode 100755 index 819be58cc..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_ipc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin deleted file mode 100755 index fa8edfb58..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_8800dc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin deleted file mode 100755 index 899571a25..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_h_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_ipc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_ipc_u02.bin deleted file mode 100755 index df2573d0b..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_ipc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin deleted file mode 100755 index 4d6285ac3..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fmacfw_patch_tbl_8800dc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_adid_8800dc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_adid_8800dc_u02.bin deleted file mode 100755 index 3e90e35af..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_adid_8800dc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_adid_8800dc_u02h.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_adid_8800dc_u02h.bin deleted file mode 100755 index e3bc1f0d4..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_adid_8800dc_u02h.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_8800dc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_8800dc_u02.bin deleted file mode 100755 index 220c6a894..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_8800dc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_8800dc_u02h.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_8800dc_u02h.bin deleted file mode 100755 index 30053f00b..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_8800dc_u02h.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_table_8800dc_u02.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_table_8800dc_u02.bin deleted file mode 100755 index 7555f5d4a..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_table_8800dc_u02.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin deleted file mode 100755 index 1cb983077..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/fw_patch_table_8800dc_u02h.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/lmacfw_rf_8800dc.bin b/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/lmacfw_rf_8800dc.bin deleted file mode 100755 index d0f3215d2..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/aic8800dc_fw/lmacfw_rf_8800dc.bin and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/ccm.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/ccm.ko deleted file mode 100644 index 71ff2213f..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/ccm.ko and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/cfg80211.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/cfg80211.ko deleted file mode 100644 index 285c94bf3..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/cfg80211.ko and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/ctr.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/ctr.ko deleted file mode 100644 index 7acf4f90c..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/ctr.ko and /dev/null differ diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/insmod_wifi.sh b/sysdrv/tools/board/emmc/emmc_wifi_ko/insmod_wifi.sh deleted file mode 100755 index ffba12b42..000000000 --- a/sysdrv/tools/board/emmc/emmc_wifi_ko/insmod_wifi.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -cmd=$(realpath $0) -_DIR=$(dirname $cmd) -cd $_DIR - -export PATH=$PATH:/ko - -#aic8800 -if [ -f /usr/ko/aic8800_fdrv.ko ]; then - mkdir -p /oem/usr/ko - cp /usr/ko/aic8800dc_fw /oem/usr/ko -r - insmod cfg80211.ko - insmod libarc4.ko - insmod ctr.ko - insmod ccm.ko - #insmod libaes.ko - #insmod aes_generic.ko - insmod aic8800_bsp.ko - sleep 0.2 - insmod aic8800_fdrv.ko - sleep 2 - insmod aic8800_btlpm.ko - sleep 0.1 -fi diff --git a/sysdrv/tools/board/emmc/emmc_wifi_ko/libarc4.ko b/sysdrv/tools/board/emmc/emmc_wifi_ko/libarc4.ko deleted file mode 100644 index 512cfb881..000000000 Binary files a/sysdrv/tools/board/emmc/emmc_wifi_ko/libarc4.ko and /dev/null differ diff --git a/sysdrv/tools/board/luckfox_config/S99luckfoxconfigload b/sysdrv/tools/board/luckfox_config/S99luckfoxconfigload index 9dba3fa8d..3f850145c 100755 --- a/sysdrv/tools/board/luckfox_config/S99luckfoxconfigload +++ b/sysdrv/tools/board/luckfox_config/S99luckfoxconfigload @@ -3,6 +3,9 @@ load_luckfoxconfig() { if [ -f /usr/bin/luckfox-config ]; then luckfox-config load + fi + if [ "$(cat /proc/device-tree/model)" == "Luckfox Pico Ultra" ] || + [ "$(cat /proc/device-tree/model)" == "Luckfox Pico Ultra W" ]; then luckfox_switch_rgb_resolution & fi } diff --git a/sysdrv/tools/board/luckfox_config/luckfox-config b/sysdrv/tools/board/luckfox_config/luckfox-config index d1de74761..ab73a2aac 100755 --- a/sysdrv/tools/board/luckfox_config/luckfox-config +++ b/sysdrv/tools/board/luckfox_config/luckfox-config @@ -407,8 +407,8 @@ function luckfox_pico_mini_pin_diagram_file() { PWM4_M2 - SPI0_M0_CLK - GPIO1_C1 | | GPIO1_C6 - - PWM10_M1 PWM5_M2 - SPI0_M0_MOSI - GPIO1_C2 | | GPIO1_D3 - - PWM11_M2 PWM6_M2 - SPI0_M0_MISO - GPIO1_C3 | | GPIO1_D2 - - PWM0_M1 - PWM8_M1 - UART4_M1_RX - GPIO1_C4 | | GPIO1_D1 - - PWM10_M2 - PWM9_M1 - UART4_M1_TX - GPIO1_C5 | | GPIO1_D0 - SARADC_M1 - PWM3_M2 + PWM8_M1 - UART4_M1_RX - GPIO1_C4 | | GPIO1_D1 - UART3_M1_RX - PWM10_M2 + PWM9_M1 - UART4_M1_TX - GPIO1_C5 | | GPIO1_D0 - UART3_M1_TX - PWM3_M2 + - + - + EOF } @@ -2710,7 +2710,7 @@ elif [ "$1" == "rgb_switch" ]; then "18" "16" \ "2" "2" \ "0" "0" \ - "0" "1" + "0" "0" elif [ "$(luckfox_get_pin_cfg "RGB_HACTIVE")" == "720" ]; then # 720 -> 480 echo "****************************************************"