input: touchscreen: hyn: hyn touchscreens support

Type: Function
Redmine ID: #N/A
Associated modifications: N/A
Test: N/A

Signed-off-by: Zhibin Huang <zhibin.huang@rock-chips.com>
Change-Id: I649a447919003574d907b83b10ba3fd7496ad492
This commit is contained in:
Zhibin Huang
2025-05-26 10:48:04 +08:00
committed by Tao Huang
parent cfc8a04804
commit a40956e0e5
31 changed files with 22010 additions and 0 deletions

View File

@@ -469,6 +469,9 @@ config TOUCHSCREEN_HYCON_HY46XX
To compile this driver as a module, choose M here: the
module will be called hycon-hy46xx.
config TOUCHSCREEN_HYN
tristate "HYN touchscreens support"
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C

View File

@@ -60,6 +60,7 @@ gslx680-pad-y := gslx680_pad.o gsl_point_id.o
obj-$(CONFIG_TOUCHSCREEN_GT1X) += gt1x/
obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_HYN) += hyn/
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o
obj-$(CONFIG_TOUCHSCREEN_IMAGIS) += imagis.o

View File

@@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_TOUCHSCREEN_HYN) += hynitron_touch.o
hynitron_touch-objs += hyn_core.o hyn_lib/hyn_i2c.o hyn_lib/hyn_spi.o hyn_lib/hyn_ts_ext.o hyn_lib/hyn_fs_node.o
hynitron_touch-objs += hyn_lib/hyn_tool.o
hynitron_touch-objs += hyn_lib/hyn_gesture.o
hynitron_touch-objs += hyn_lib/hyn_prox.o
hynitron_touch-objs += hyn_chips/hyn_cst66xx.o
hynitron_touch-objs += hyn_chips/hyn_cst3240.o
hynitron_touch-objs += hyn_chips/hyn_cst92xx.o
hynitron_touch-objs += hyn_chips/hyn_cst3xx.o
hynitron_touch-objs += hyn_chips/hyn_cst7xx.o
hynitron_touch-objs += hyn_chips/hyn_cst8xxT.o
hynitron_touch-objs += hyn_chips/hyn_cst226se.o
hynitron_touch-objs += hyn_chips/hyn_cst36xxes.o

View File

@@ -0,0 +1,60 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_cfg.h
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _HYNITRON_CFG_H
#define _HYNITRON_CFG_H
#define I2C_PORT
#ifdef I2C_PORT
#define I2C_USE_DMA (1) //0:soft 1:DMA 2:MTK_DMA
#else
#define SPI_MODE (0)
#define SPI_DELAY_CS (10) //us
#define SPI_CLOCK_FREQ (8000000)
#define I2C_USE_DMA (0)
// #define CONFIG_BUS_SPI //default:0 MTK can try define
#endif
#define HYN_TRANSFER_LIMIT_LEN (2048) //need >= 8
#define HYN_POWER_ON_UPDATA (1) //updata
#ifdef CONFIG_MODULES
#define HYN_GKI_VER (1) //GKI version need enable
#else
#define HYN_GKI_VER (0) //GKI version need enable
#endif
#define HYN_APK_DEBUG_EN (1)
#define HYN_GESTURE_EN (0) //gesture
#define HYN_PROX_TYEP (0) //0:disable 1:default 2:mtk_sensor 3:mtk_alps 4:Spread misc
#define KEY_USED_POS_REPORT (0)
#define ESD_CHECK_EN (0)
#define HYN_WAKE_LOCK_EN (0)
#define HYN_MT_PROTOCOL_B_EN (1)
//selftest cfg
#define HYN_TP0_TEST_LOG_SAVE (0)
#define HYN_DRIVER_VERSION "== Hynitron V2.11 20250217 =="
#endif

View File

@@ -0,0 +1,503 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst226se_fw.h
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef HYNITRON_FIRMWARE_H
#define HYNITRON_FIRMWARE_H
static const uint8_t fw_bin[] = {
0x6C,0x03,0x00,0x20,0x09,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,0x03,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xF9,0x00,0x00,0x00,0xFB,0x00,0x00,0x00,0x1B,0x01,0x00,0x00,0x37,0x01,0x00,0x00,
0x4B,0x01,0x00,0x00,0x00,0xF0,0x02,0xF8,0x00,0xF0,0x3E,0xF8,0x0C,0xA0,0x30,0xC8,
0x08,0x38,0x24,0x18,0x2D,0x18,0xA2,0x46,0x67,0x1E,0xAB,0x46,0x54,0x46,0x5D,0x46,
0xAC,0x42,0x01,0xD1,0x00,0xF0,0x30,0xF8,0x7E,0x46,0x0F,0x3E,0x0F,0xCC,0xB6,0x46,
0x01,0x26,0x33,0x42,0x00,0xD0,0xFB,0x1A,0xA2,0x46,0xAB,0x46,0x33,0x43,0x18,0x47,
0x04,0x18,0x00,0x00,0x24,0x18,0x00,0x00,0x10,0x3A,0x02,0xD3,0x78,0xC8,0x78,0xC1,
0xFA,0xD8,0x52,0x07,0x01,0xD3,0x30,0xC8,0x30,0xC1,0x01,0xD5,0x04,0x68,0x0C,0x60,
0x70,0x47,0x00,0x00,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x10,0x3A,0x01,0xD3,
0x78,0xC1,0xFB,0xD8,0x52,0x07,0x00,0xD3,0x30,0xC1,0x00,0xD5,0x0B,0x60,0x70,0x47,
0x1F,0xB5,0x1F,0xBD,0x10,0xB5,0x10,0xBD,0x01,0xF0,0x05,0xFA,0x11,0x46,0xFF,0xF7,
0xF7,0xFF,0x00,0xF0,0x53,0xF9,0x01,0xF0,0x1D,0xFA,0x03,0xB4,0xFF,0xF7,0xF2,0xFF,
0x03,0xBC,0x01,0xF0,0x21,0xFA,0x00,0x00,0xFE,0xE7,0x1D,0x49,0x48,0x88,0x48,0x80,
0x1C,0x48,0x02,0x7C,0xFF,0x2A,0x02,0xD2,0x02,0x7C,0x52,0x1C,0x02,0x74,0x00,0x7C,
0x18,0x28,0x01,0xD2,0x00,0x20,0x88,0x80,0x70,0x47,0x17,0x49,0x8A,0x79,0x15,0x48,
0x20,0x38,0x80,0x6F,0x43,0x7A,0x9A,0x43,0x8A,0x71,0x40,0x7A,0x48,0x72,0x11,0x49,
0x01,0x20,0x08,0x74,0x70,0x47,0x10,0xB5,0x0F,0x48,0x80,0x30,0x81,0x88,0x80,0x22,
0x11,0x43,0x81,0x80,0x0D,0xF0,0xEC,0xFE,0x10,0xBD,0x10,0xB5,0x09,0x48,0x20,0x30,
0x01,0x78,0x49,0x06,0x08,0xD5,0x02,0x78,0x80,0x21,0x0A,0x43,0x02,0x70,0x07,0x48,
0x42,0x88,0x8A,0x43,0x42,0x80,0x10,0xBD,0x00,0xF0,0xA2,0xFD,0x10,0xBD,0x00,0x00,
0x00,0x02,0x00,0x40,0x90,0x0A,0x00,0x20,0x00,0x10,0x00,0x40,0x00,0x20,0x00,0x40,
0x10,0xB5,0x8A,0x48,0x8A,0x4B,0x80,0x6F,0x01,0x46,0x80,0x31,0x0C,0x46,0x0A,0x7F,
0x60,0x30,0x41,0x79,0x00,0x2A,0x06,0xD0,0x12,0x02,0x0A,0x43,0x5A,0x81,0xFF,0x21,
0x23,0x31,0x59,0x80,0x03,0xE0,0x59,0x81,0xFF,0x21,0x03,0x31,0x59,0x80,0xA1,0x8E,
0xD9,0x80,0x81,0x79,0x02,0x79,0x09,0x02,0x11,0x43,0x19,0x81,0x01,0x7A,0xC0,0x79,
0x09,0x02,0x01,0x43,0x7A,0x48,0x20,0x38,0xC1,0x81,0x10,0xBD,0x10,0xB5,0x77,0x48,
0x78,0x49,0x81,0x67,0x78,0x49,0xC1,0x61,0x78,0x49,0x01,0x62,0x78,0x49,0x41,0x62,
0x78,0x49,0x81,0x62,0x78,0x49,0xC1,0x62,0x78,0x49,0xC1,0x67,0x78,0x49,0x41,0x64,
0x78,0x49,0x81,0x64,0x78,0x49,0xC1,0x64,0x78,0x49,0x01,0x65,0x78,0x49,0x41,0x65,
0x78,0x49,0x00,0x20,0xC8,0x80,0xC8,0x60,0x48,0x70,0x88,0x70,0xC8,0x70,0x08,0x71,
0x48,0x71,0x7D,0x22,0xD2,0x00,0x0A,0x81,0x65,0x4A,0x01,0x21,0x60,0x3A,0x91,0x75,
0x6A,0x49,0xA8,0x22,0x40,0x31,0x0A,0x73,0xC8,0x72,0x02,0x20,0x88,0x71,0x03,0x20,
0x48,0x71,0x0D,0xF0,0xD9,0xFE,0x0D,0xF0,0xD3,0xFE,0x3C,0x20,0x0D,0xF0,0xCC,0xFE,
0x0D,0xF0,0xC6,0xFE,0x0D,0xF0,0xC0,0xFE,0x00,0xF0,0xC5,0xFB,0x0D,0xF0,0xB8,0xFE,
0x00,0xF0,0xED,0xFB,0x10,0xBD,0xFE,0xB5,0x63,0x4E,0x00,0x21,0x00,0x25,0x63,0x4C,
0x00,0x22,0x68,0x46,0x42,0x54,0x0A,0x20,0x61,0x4A,0x48,0x43,0x82,0x18,0x23,0x20,
0x40,0x01,0x13,0x18,0x00,0x22,0x30,0x78,0xC7,0x00,0x18,0x78,0x38,0x1A,0x80,0xB2,
0x85,0x42,0x00,0xD2,0x05,0x46,0x84,0x42,0x00,0xD9,0x04,0x46,0x5B,0x1C,0x52,0x1C,
0xD2,0xB2,0x0A,0x2A,0xF1,0xD3,0x28,0x1B,0x6B,0x46,0x58,0x54,0x76,0x1C,0x49,0x1C,
0xC9,0xB2,0x0C,0x29,0xDA,0xD3,0x51,0x49,0x00,0x20,0x1A,0x5C,0x8A,0x42,0x00,0xD2,
0x11,0x46,0x40,0x1C,0xC0,0xB2,0x0C,0x28,0xF7,0xD3,0x4A,0x4C,0x00,0x20,0x60,0x70,
0x1A,0x5C,0x65,0x78,0x52,0x1A,0x52,0x19,0x62,0x70,0x40,0x1C,0xC0,0xB2,0x0C,0x28,
0xF6,0xD3,0xFE,0xBD,0xF8,0xB5,0x35,0x4C,0x40,0x34,0x20,0x78,0x01,0x21,0x08,0x43,
0x20,0x70,0x44,0x4F,0x31,0x4D,0x3F,0x4E,0x4C,0xE0,0x0D,0xF0,0x65,0xFE,0xF0,0x68,
0x40,0x1C,0xF0,0x60,0x38,0x7A,0x00,0x28,0x03,0xD0,0x2C,0x49,0x18,0x20,0x20,0x31,
0x08,0x74,0x0D,0xF0,0x55,0xFE,0x20,0x78,0xC0,0x07,0x01,0xD0,0x55,0x20,0x78,0x70,
0x0D,0xF0,0x4A,0xFE,0xFF,0xF7,0x9F,0xFF,0xA8,0x6F,0x20,0x30,0x40,0x78,0x00,0x28,
0x01,0xD0,0x0D,0xF0,0x3D,0xFE,0xA8,0x6F,0x21,0x21,0x09,0x5C,0x09,0x09,0x06,0xD0,
0x1E,0x49,0x60,0x30,0x60,0x39,0x89,0x7B,0xC0,0x7A,0x81,0x42,0x1E,0xD1,0x0D,0xF0,
0x2B,0xFE,0x00,0x20,0x30,0x70,0x0D,0xF0,0x23,0xFE,0x18,0x49,0x02,0x20,0x40,0x39,
0x48,0x76,0x00,0xF0,0xBA,0xF8,0x0D,0xF0,0x17,0xFE,0x00,0xF0,0x1E,0xFA,0x00,0xF0,
0x70,0xFB,0x0D,0xF0,0x0D,0xFE,0x0D,0xF0,0xFF,0xFD,0x23,0x48,0x0D,0xF0,0xF8,0xFD,
0x0D,0xF0,0xF2,0xFD,0x00,0xF0,0x5A,0xFF,0x00,0xF0,0x58,0xFB,0x00,0xF0,0x60,0xF9,
0x00,0xF0,0x60,0xF8,0xA0,0x78,0x06,0x28,0xAF,0xD1,0xF8,0xBD,0xFF,0xF7,0x1E,0xFF,
0x06,0x4C,0x40,0x34,0xA0,0x78,0x00,0x28,0x04,0xD0,0x06,0x28,0xFA,0xD1,0x0D,0xF0,
0xC3,0xFD,0xF7,0xE7,0xFF,0xF7,0x96,0xFF,0xF4,0xE7,0x00,0x00,0x70,0x0A,0x00,0x20,
0x80,0x10,0x00,0x40,0x48,0x15,0x00,0x00,0x7A,0x17,0x00,0x00,0x8C,0x17,0x00,0x00,
0x68,0x18,0x00,0x00,0x48,0x17,0x00,0x00,0x68,0x17,0x00,0x00,0x10,0x00,0x00,0x20,
0x31,0x04,0x00,0x00,0x39,0x04,0x00,0x00,0xEF,0x0A,0x00,0x00,0xE7,0x0D,0x00,0x00,
0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x20,0x84,0x08,0x00,0x20,0xFF,0xFF,0x00,0x00,
0x70,0x03,0x00,0x20,0x64,0x00,0x00,0x20,0x9B,0x07,0x00,0x00,0x0B,0x49,0x0A,0x48,
0xC8,0x60,0xBF,0xF3,0x40,0x8F,0xFE,0xE7,0x10,0xB5,0xFF,0xF7,0xBF,0xFF,0x10,0xBD,
0x0F,0xB5,0x00,0x90,0x01,0x91,0x01,0x98,0x02,0x90,0x00,0x98,0x03,0x90,0x68,0x46,
0x0F,0xC8,0x04,0xB0,0x00,0xBD,0x00,0x00,0x04,0x00,0xFA,0x05,0x00,0xED,0x00,0xE0,
0x10,0xB5,0x00,0xF0,0xB5,0xFF,0x10,0xBD,0x10,0xB5,0x00,0xF0,0xB1,0xFF,0x08,0x46,
0x10,0xBD,0x00,0x00,0x70,0xB5,0xF9,0x48,0x00,0xE0,0x30,0xBF,0x01,0x7C,0x00,0x29,
0xFB,0xD0,0xF6,0x4C,0x20,0x34,0x20,0x78,0x00,0x07,0x24,0xD5,0xF4,0x4E,0x01,0x25,
0x35,0x76,0xA8,0x07,0x01,0x68,0x08,0x22,0x11,0x43,0x01,0x60,0x00,0x20,0x08,0xF0,
0x6C,0xFD,0xEF,0x4A,0x20,0x3A,0x10,0x78,0x21,0x46,0x40,0x39,0x89,0x6F,0x20,0x31,
0x8B,0x79,0x29,0x46,0x99,0x40,0x08,0x43,0x10,0x70,0x20,0x78,0xEF,0x21,0x08,0x40,
0x20,0x70,0x00,0xE0,0x30,0xBF,0x20,0x78,0xC0,0x06,0xFB,0xD5,0x00,0x20,0x30,0x76,
0x20,0x78,0x28,0x43,0x20,0x70,0xE3,0x4A,0x50,0x68,0x40,0x1C,0x50,0x60,0xE2,0x49,
0x03,0x0E,0x8B,0x72,0x03,0x0C,0x4B,0x72,0x03,0x0A,0x0B,0x72,0xC8,0x71,0x10,0x7A,
0x00,0x28,0x01,0xD0,0x30,0xBF,0xFD,0xE7,0x70,0xBD,0x30,0xB5,0xDB,0x48,0x00,0x68,
0x0A,0x28,0x31,0xD9,0x00,0x25,0xDA,0x49,0x0A,0x46,0x00,0x23,0x00,0x20,0x14,0x78,
0xFF,0x2C,0x00,0xD1,0x01,0x25,0x52,0x1C,0x40,0x1C,0xC0,0xB2,0x0A,0x28,0xF6,0xD3,
0x5B,0x1C,0xDB,0xB2,0x0C,0x2B,0xF1,0xD3,0x00,0x24,0x00,0x22,0x00,0x20,0x0B,0x78,
0x93,0x42,0x00,0xD9,0x1A,0x46,0x49,0x1C,0x40,0x1C,0xC0,0xB2,0x0A,0x28,0xF6,0xD3,
0x0B,0x3A,0x31,0x2A,0x00,0xD2,0x01,0x25,0x64,0x1C,0xE4,0xB2,0x0C,0x2C,0xEC,0xD3,
0xC8,0x49,0x00,0x2D,0x09,0xD0,0xC8,0x48,0x00,0x78,0x00,0x28,0x04,0xD1,0x08,0x78,
0x64,0x28,0x01,0xD2,0x40,0x1C,0x08,0x70,0x30,0xBD,0x00,0x20,0x08,0x70,0x30,0xBD,
0xF0,0xB5,0x85,0xB0,0x00,0x26,0xC1,0xA0,0x03,0xC8,0x02,0x91,0x01,0x90,0xB7,0x48,
0x80,0x38,0xC0,0x7C,0xB5,0x49,0x20,0x39,0x04,0x91,0x00,0x28,0x1D,0xD0,0x01,0xA9,
0x00,0x20,0xB7,0x4A,0x17,0x23,0xDC,0x3A,0x9B,0x01,0x11,0xE0,0x24,0x24,0x44,0x43,
0xA4,0x18,0xE4,0x18,0x24,0x7C,0x01,0x2C,0x08,0xD1,0x08,0x70,0x49,0x1C,0x76,0x1C,
0xF6,0xB2,0x04,0x9C,0xA4,0x6F,0xE4,0x7A,0xB4,0x42,0x06,0xD0,0x40,0x1C,0xC0,0xB2,
0x04,0x9C,0xA4,0x6F,0xE4,0x7A,0x84,0x42,0xE8,0xD8,0xA7,0x4C,0x40,0x3C,0x01,0xAD,
0x00,0x27,0xA2,0x48,0x40,0x38,0x03,0x90,0x0A,0xE0,0x00,0x2F,0x18,0xD0,0x28,0x78,
0x6A,0x46,0x21,0x46,0x08,0xF0,0x8B,0xF9,0x6D,0x1C,0x64,0x1D,0x7F,0x1C,0xFF,0xB2,
0xB7,0x42,0xF2,0xD3,0x03,0x98,0x00,0x7C,0xC1,0x09,0x24,0xD0,0x00,0x2E,0x17,0xD0,
0x20,0x70,0x03,0x98,0x80,0x7C,0x60,0x70,0xA4,0x1C,0xAB,0x20,0x20,0x70,0x18,0xE0,
0x28,0x78,0x6A,0x46,0x21,0x46,0x08,0xF0,0x72,0xF9,0x6D,0x1C,0x03,0x98,0x00,0x7C,
0xC0,0x09,0xC0,0x01,0x30,0x43,0x60,0x71,0xAB,0x20,0xA0,0x71,0xE4,0x1D,0xDD,0xE7,
0x20,0x70,0x03,0x98,0x80,0x7C,0x60,0x70,0x80,0x20,0x60,0x71,0xA4,0x1D,0xAB,0x20,
0x20,0x70,0x64,0x1C,0x04,0xE0,0x01,0x2E,0x02,0xD9,0xAB,0x20,0x20,0x70,0x64,0x1C,
0x20,0x46,0x08,0xF0,0x35,0xF8,0x82,0x4A,0x20,0x3A,0x10,0x78,0x04,0x99,0x89,0x6F,
0x20,0x31,0x8B,0x79,0x01,0x21,0x99,0x40,0x08,0x43,0x10,0x70,0x05,0xB0,0xF0,0xBD,
0xF8,0xB5,0x7A,0x4D,0x20,0x35,0xA8,0x78,0x00,0x28,0x03,0xD0,0x0D,0xF0,0x74,0xFC,
0x00,0x28,0x36,0xD1,0x75,0x48,0x76,0x4F,0x80,0x38,0x84,0x46,0xC1,0x7C,0x76,0x48,
0x72,0x4C,0x40,0x38,0x20,0x3F,0x01,0x26,0x20,0x3C,0x00,0x29,0x0A,0xD1,0xA2,0x6F,
0x21,0x46,0x20,0x39,0x20,0x32,0x8B,0x7D,0x12,0x7A,0x93,0x42,0x05,0xD3,0x09,0x7C,
0x09,0x06,0x02,0xD5,0x61,0x78,0x00,0x29,0x24,0xD0,0x6A,0x4A,0x51,0x78,0x55,0x29,
0x06,0xD0,0x11,0x78,0x55,0x29,0x14,0xD1,0x61,0x46,0x49,0x7B,0x06,0x29,0x10,0xD1,
0x00,0x21,0x11,0x70,0x51,0x70,0x01,0x70,0xAB,0x22,0x82,0x71,0x41,0x71,0xA8,0x78,
0x00,0x28,0x07,0xD0,0x38,0x78,0xA1,0x6F,0x20,0x31,0x89,0x79,0x8E,0x40,0x30,0x43,
0x38,0x70,0xF8,0xBD,0x38,0x78,0xA1,0x6F,0x20,0x31,0x89,0x79,0x8E,0x40,0xB0,0x43,
0x38,0x70,0xF8,0xBD,0x57,0x49,0x55,0x22,0x0A,0x70,0x5B,0x49,0x09,0x78,0x00,0x29,
0x02,0xD0,0xAA,0x78,0x00,0x2A,0x3C,0xD0,0x00,0x21,0x05,0x46,0x59,0x48,0x2A,0x78,
0xAB,0x2A,0x03,0xD0,0x49,0x1C,0x89,0xB2,0x81,0x42,0xF8,0xD3,0x38,0x78,0xA1,0x6F,
0x32,0x46,0x60,0x31,0x49,0x78,0x8A,0x40,0x10,0x42,0x12,0xD1,0x01,0x20,0x0C,0xF0,
0x02,0xFF,0x38,0x78,0xA1,0x6F,0x60,0x31,0x4A,0x78,0x31,0x46,0x91,0x40,0x08,0x42,
0x07,0xD1,0x4D,0x48,0x41,0x88,0x23,0x22,0x91,0x43,0x41,0x80,0x41,0x88,0x31,0x43,
0x41,0x80,0xE5,0x67,0x0D,0xF0,0x04,0xFC,0xFF,0xF7,0x02,0xFF,0x38,0x78,0xA1,0x6F,
0x20,0x31,0x8A,0x79,0x31,0x46,0x91,0x40,0x88,0x43,0x38,0x70,0x64,0x20,0x0C,0xF0,
0xE2,0xFE,0x38,0x78,0xA1,0x6F,0x20,0x31,0x89,0x79,0x8E,0x40,0x30,0x43,0x38,0x70,
0xF8,0xBD,0x3B,0x29,0x01,0xD0,0x01,0x29,0xFA,0xD1,0x00,0x21,0x01,0x70,0x41,0x71,
0xAB,0x21,0x81,0x71,0x38,0x78,0xA1,0x6F,0x20,0x31,0x8A,0x79,0x31,0x46,0x91,0x40,
0x88,0x43,0x38,0x70,0x64,0x20,0x0C,0xF0,0xC6,0xFE,0x38,0x78,0xA1,0x6F,0x20,0x31,
0x89,0x79,0x8E,0x40,0x30,0x43,0x38,0x70,0xF8,0xBD,0xF0,0xB5,0x87,0xB0,0x00,0x20,
0x00,0x90,0x00,0x22,0x00,0x24,0x00,0x23,0x0B,0x25,0xAD,0x01,0x27,0x26,0xF6,0x43,
0x23,0x49,0x5F,0x00,0xDC,0x39,0x79,0x18,0x4F,0x19,0x38,0x21,0x79,0x5E,0xB1,0x42,
0x02,0xDA,0x40,0x18,0x00,0xB2,0x03,0xE0,0x28,0x29,0x01,0xDD,0x52,0x18,0x92,0xB2,
0x50,0x29,0x00,0xDD,0x01,0x24,0x5B,0x1C,0x1B,0xB2,0x78,0x2B,0xE8,0xDB,0x1F,0x4E,
0xF0,0x85,0x32,0x86,0x1E,0x49,0x0D,0x78,0x1E,0x49,0x06,0x95,0x0B,0x88,0x0F,0x49,
0x20,0x31,0x0F,0x2D,0x4E,0xD9,0xFF,0x25,0xF5,0x35,0xE8,0x42,0x3A,0xDA,0x00,0x28,
0x01,0xDB,0x05,0x46,0x00,0xE0,0x45,0x42,0x95,0x42,0x33,0xDD,0x08,0x78,0x01,0x22,
0x10,0x43,0x08,0x70,0x14,0x49,0x00,0x20,0x88,0x80,0x14,0x48,0x0C,0xF0,0x7B,0xFE,
0x10,0x49,0x13,0x48,0x08,0x80,0x07,0xB0,0xF0,0xBD,0x00,0x00,0x90,0x0A,0x00,0x20,
0x20,0x10,0x00,0x40,0x64,0x00,0x00,0x20,0x50,0x00,0x00,0x20,0x0C,0x00,0x00,0x20,
0x4C,0x04,0x00,0x20,0x05,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0xFF,0xFF,0xFF,0xFF,
0xFF,0x00,0x00,0x00,0x4C,0x1D,0x00,0x00,0x00,0x20,0x00,0x40,0x70,0x08,0x00,0x20,
0x01,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x00,0x02,0x00,0x40,0x88,0x13,0x00,0x00,
0x70,0x17,0x00,0x00,0xC8,0x25,0xE8,0x42,0x2A,0xDA,0x00,0x28,0x01,0xDB,0x07,0x46,
0x00,0xE0,0x47,0x42,0xFE,0x4D,0x9F,0x42,0x22,0xDD,0x00,0x28,0x00,0xDA,0x40,0x42,
0x28,0x80,0x1D,0xE0,0x00,0x28,0x01,0xDB,0x05,0x46,0x00,0xE0,0x45,0x42,0x95,0x42,
0x07,0xDD,0xFF,0x25,0x91,0x35,0xE8,0x42,0x03,0xDA,0xF5,0x4B,0xF5,0x48,0x18,0x80,
0x0E,0xE0,0xC8,0x25,0xE8,0x42,0x0B,0xDA,0x00,0x28,0x01,0xDB,0x07,0x46,0x00,0xE0,
0x47,0x42,0xEF,0x4D,0x9F,0x42,0x03,0xDD,0x00,0x28,0x00,0xDA,0x40,0x42,0x28,0x80,
0xED,0x4D,0xEE,0x48,0x2B,0x78,0x00,0x78,0x05,0x90,0xED,0x48,0x14,0x2B,0x00,0x78,
0x04,0x90,0x0B,0xD9,0x05,0x98,0x00,0x28,0x08,0xD1,0x04,0x98,0x00,0x28,0x05,0xD1,
0x4B,0x20,0xC0,0x00,0x82,0x42,0x01,0xD2,0x00,0x2C,0x38,0xD0,0x00,0x20,0x02,0x90,
0x00,0x20,0x00,0x21,0x01,0x91,0x02,0x99,0x4A,0x00,0xE2,0x49,0x52,0x18,0x5F,0x21,
0xC9,0x00,0x53,0x18,0x1D,0x46,0x00,0x22,0x00,0x21,0x59,0x5E,0x08,0x18,0x00,0xB2,
0x01,0x9C,0xA1,0x42,0x00,0xDD,0x01,0x91,0x14,0x33,0x52,0x1C,0xD2,0xB2,0x0C,0x2A,
0xF2,0xD3,0x0C,0x21,0x00,0xF0,0x34,0xFD,0x04,0xB2,0x00,0x98,0xA0,0x42,0x01,0xDA,
0xA0,0xB2,0x00,0x90,0x00,0x27,0x00,0x2C,0x21,0xDD,0x00,0x20,0x28,0x5E,0x03,0x90,
0xA0,0x42,0x16,0xDB,0x03,0x21,0x01,0x98,0x00,0xF0,0x22,0xFD,0xA0,0x42,0x1C,0xDA,
0xE0,0x0F,0x00,0x19,0x41,0x10,0x03,0x98,0x40,0x1A,0x28,0x80,0x15,0xE0,0x08,0x78,
0x01,0x22,0x10,0x43,0x08,0x70,0xC2,0x49,0xC2,0x48,0x08,0x80,0x00,0x20,0x28,0x70,
0x51,0xE7,0x03,0x98,0x00,0x28,0x08,0xDD,0x01,0x20,0x28,0x80,0x05,0xE0,0x00,0x20,
0x28,0x5E,0xA0,0x42,0x01,0xDC,0x00,0x1B,0x28,0x80,0x14,0x35,0x7F,0x1C,0xFF,0xB2,
0x0C,0x2F,0xD0,0xD3,0x02,0x98,0x40,0x1C,0xC0,0xB2,0x02,0x90,0x02,0x98,0x0A,0x28,
0xA6,0xD3,0xB9,0x48,0x80,0x7A,0xF0,0x84,0x06,0x98,0x30,0x85,0x05,0x98,0x70,0x85,
0x04,0x98,0xB0,0x85,0xB5,0x48,0x00,0x68,0x70,0x86,0x00,0x14,0xB0,0x86,0xAC,0x48,
0x00,0x88,0xF0,0x86,0x27,0xE7,0x30,0xB5,0xB1,0x48,0x83,0x78,0xAE,0x49,0x01,0x22,
0x60,0x31,0x89,0x6F,0x14,0x46,0x20,0x31,0x8D,0x79,0xAC,0x40,0xA3,0x43,0x83,0x70,
0x43,0x78,0x8D,0x79,0x14,0x46,0xAC,0x40,0xA3,0x43,0x43,0x70,0x03,0x78,0x8D,0x79,
0x14,0x46,0xAC,0x40,0x23,0x43,0x03,0x70,0x03,0x79,0x8D,0x79,0x14,0x46,0xAC,0x40,
0x23,0x43,0x03,0x71,0x43,0x79,0x8D,0x79,0x14,0x46,0xAC,0x40,0xA3,0x43,0x43,0x71,
0xC3,0x78,0x89,0x79,0x8A,0x40,0x13,0x43,0xC3,0x70,0x30,0xBD,0x70,0x47,0x9D,0x49,
0x00,0x20,0x08,0x70,0x48,0x70,0x48,0x60,0x88,0x70,0x9B,0x4A,0xD0,0x72,0x08,0x72,
0x70,0x47,0xF8,0xB5,0x99,0x4A,0x98,0x4B,0xD8,0x7A,0x00,0x28,0x4E,0xD0,0x00,0x20,
0x00,0x24,0x28,0x25,0x90,0x49,0x60,0x31,0x00,0x91,0x8E,0x6F,0xF1,0x79,0x00,0x29,
0x00,0xD0,0x1E,0x25,0x00,0x21,0x08,0xE0,0x00,0x27,0xD7,0x5F,0x0A,0x2F,0x01,0xDB,
0x40,0x1C,0x80,0xB2,0x92,0x1C,0x49,0x1C,0x89,0xB2,0xA9,0x42,0xF4,0xD3,0x89,0x49,
0x0A,0x28,0x08,0xD2,0x06,0x28,0x02,0xD3,0xD8,0x7A,0x40,0x06,0x03,0xD1,0x82,0x48,
0xC0,0x7B,0x01,0x28,0x08,0xD9,0xD8,0x7A,0x80,0x28,0x00,0xD1,0x01,0x24,0x81,0x20,
0xD8,0x72,0x14,0x20,0x88,0x70,0x0B,0xE0,0x88,0x78,0x00,0x28,0x02,0xD0,0x40,0x1E,
0x88,0x70,0x05,0xE0,0xD8,0x7A,0x81,0x28,0x00,0xD1,0x01,0x24,0x80,0x20,0xD8,0x72,
0x00,0x2C,0x13,0xD0,0x76,0x4C,0x20,0x78,0x20,0x36,0xB2,0x79,0x01,0x25,0x29,0x46,
0x91,0x40,0x88,0x43,0x20,0x70,0x28,0x20,0x0C,0xF0,0x1D,0xFD,0x20,0x78,0x00,0x99,
0x89,0x6F,0x20,0x31,0x89,0x79,0x8D,0x40,0x28,0x43,0x20,0x70,0xF8,0xBD,0xF8,0xB5,
0x0D,0x46,0x07,0x9F,0x06,0x9E,0x11,0x46,0x67,0x4A,0x60,0x32,0x90,0x6F,0x40,0x30,
0x00,0x2D,0x07,0xD0,0x00,0x2E,0x02,0xD0,0x1E,0x24,0x04,0x57,0x09,0xE0,0x1D,0x24,
0x04,0x57,0x06,0xE0,0x00,0x2F,0x02,0xD0,0x1C,0x24,0x04,0x57,0x01,0xE0,0x1B,0x24,
0x04,0x57,0x00,0x20,0x18,0x5E,0x00,0x28,0x00,0xDA,0x40,0x42,0xC0,0x01,0x0B,0x46,
0x00,0x21,0x52,0x6C,0x59,0x5E,0x90,0x47,0x7F,0x28,0x00,0xDD,0x7F,0x20,0xFF,0x21,
0x01,0x31,0x00,0x2E,0x01,0xD0,0x00,0x2D,0x03,0xD1,0x00,0x2F,0x02,0xD0,0x00,0x2D,
0x00,0xD1,0x08,0x1A,0x00,0x19,0x88,0x42,0x01,0xDD,0x08,0x46,0xF8,0xBD,0x00,0x28,
0xFC,0xDA,0x00,0x20,0xF8,0xBD,0xF0,0xB5,0x85,0xB0,0x50,0x4E,0x4A,0x48,0x60,0x30,
0x80,0x6F,0x01,0x79,0x02,0x91,0xC0,0x78,0x01,0x90,0x00,0x25,0x46,0x48,0x04,0x90,
0x39,0xE0,0x68,0x00,0x34,0x5E,0x87,0x19,0x14,0x20,0x38,0x5E,0x00,0x90,0x04,0x98,
0x80,0x7A,0xA0,0x42,0x11,0xDA,0x00,0x98,0x40,0x00,0xA0,0x42,0x0D,0xDA,0x21,0x11,
0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0,0xFB,0xFB,0x00,0x99,0x40,0x18,0x00,0xB2,
0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,0xB8,0x82,0x38,0x46,0xC0,0x30,0x1C,0x24,
0x03,0x90,0x04,0x5F,0x08,0x27,0xC7,0x5F,0x04,0x98,0x80,0x7A,0xA0,0x42,0x10,0xDA,
0x78,0x00,0xA0,0x42,0x0D,0xDA,0x21,0x11,0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0,
0xDF,0xFB,0xC0,0x19,0x00,0xB2,0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,0x03,0x99,
0x08,0x81,0x6D,0x1C,0xED,0xB2,0x02,0x98,0x85,0x42,0xC2,0xD3,0x00,0x27,0x3A,0xE0,
0x38,0x46,0x14,0x21,0x48,0x43,0x34,0x5E,0x85,0x19,0x02,0x20,0x28,0x5E,0x00,0x90,
0x04,0x98,0x80,0x7A,0xA0,0x42,0x11,0xDA,0x00,0x98,0x40,0x00,0xA0,0x42,0x0D,0xDA,
0x21,0x11,0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0,0xBA,0xFB,0x00,0x99,0x40,0x18,
0x00,0xB2,0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,0x68,0x80,0x12,0x24,0x2C,0x5F,
0x10,0x20,0x28,0x5E,0x00,0x90,0x04,0x98,0x80,0x7A,0xA0,0x42,0x11,0xDA,0x00,0x98,
0x40,0x00,0xA0,0x42,0x0D,0xDA,0x21,0x11,0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0,
0x9F,0xFB,0x00,0x99,0x40,0x18,0x00,0xB2,0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,
0x28,0x82,0x7F,0x1C,0xFF,0xB2,0x01,0x98,0x87,0x42,0xC1,0xD3,0xDE,0xE4,0x00,0x00,
0x08,0x00,0x00,0x20,0x70,0x17,0x00,0x00,0x05,0x00,0x00,0x20,0x02,0x00,0x00,0x20,
0x03,0x00,0x00,0x20,0x70,0x03,0x00,0x20,0x10,0x0A,0x00,0x20,0x0C,0x00,0x00,0x20,
0x00,0x10,0x00,0x40,0x64,0x00,0x00,0x20,0x50,0x00,0x00,0x20,0x68,0x06,0x00,0x20,
0xF8,0xB5,0xF7,0x4C,0xA3,0x88,0xCF,0x20,0x03,0x40,0x07,0x21,0xF5,0x48,0x09,0x02,
0x42,0x18,0x35,0x21,0x49,0x01,0x45,0x18,0x0D,0x21,0xC9,0x01,0x40,0x18,0xF2,0x4F,
0xD6,0x6F,0x81,0x6B,0x01,0x2B,0x1C,0xD0,0x05,0x2B,0x08,0xD0,0x00,0x22,0x09,0x2B,
0x01,0xD0,0xA2,0x80,0xF8,0xBD,0x6A,0x75,0xE2,0x88,0xD2,0x07,0x04,0xD0,0xB9,0x42,
0x05,0xD1,0xA5,0x20,0xE0,0x80,0x09,0xE0,0x10,0x20,0xA0,0x80,0xF8,0xBD,0x72,0x5C,
0xE2,0x80,0x49,0x1C,0x81,0x63,0x51,0x29,0x00,0xD3,0x87,0x63,0x14,0x20,0xA0,0x80,
0xF8,0xBD,0x6B,0x7D,0x02,0x2B,0x56,0xD2,0x00,0x2B,0x18,0xD0,0xE3,0x88,0x09,0x02,
0xC9,0x18,0x8E,0xB2,0xD1,0x21,0x09,0x02,0x71,0x1A,0x20,0x29,0x14,0xD8,0xF0,0xB2,
0x07,0xF0,0x7A,0xFE,0xD9,0x48,0x86,0x42,0x4F,0xD1,0x01,0x20,0x0D,0xF0,0x4C,0xF9,
0xD7,0x49,0x18,0x20,0x08,0x74,0xD7,0x49,0x01,0x20,0x08,0x72,0x45,0xE0,0xD6,0x49,
0xD1,0x67,0xE1,0x88,0x81,0x63,0x40,0xE0,0xD0,0x49,0xCE,0x39,0x8E,0x42,0x16,0xD1,
0xD2,0x48,0x01,0x68,0xD0,0x48,0x0A,0x0E,0x40,0x30,0x02,0x70,0x0A,0x0C,0x42,0x70,
0x0A,0x0A,0x82,0x70,0xC1,0x70,0x01,0x78,0x42,0x78,0x89,0x18,0x82,0x78,0xC3,0x78,
0xD2,0x18,0x89,0x18,0xA5,0x31,0x0A,0x0A,0x02,0x71,0x41,0x71,0x25,0xE0,0xC8,0x49,
0x71,0x18,0x23,0x29,0x04,0xD8,0x81,0x63,0xEF,0x20,0x40,0x01,0xD0,0x67,0x1C,0xE0,
0xC3,0x49,0x30,0x39,0x71,0x18,0x20,0x29,0x04,0xD8,0x81,0x63,0x77,0x20,0x80,0x01,
0xD0,0x67,0x12,0xE0,0x0D,0x21,0x09,0x03,0x71,0x1A,0x50,0x29,0x01,0xD8,0x81,0x63,
0x0B,0xE0,0x87,0x63,0x09,0xE0,0xB9,0x42,0x07,0xD0,0xE2,0x88,0x72,0x54,0x81,0x6B,
0x49,0x1C,0x81,0x63,0x51,0x29,0x00,0xD3,0x87,0x63,0x68,0x7D,0x40,0x1C,0x68,0x75,
0x10,0x20,0xA0,0x80,0xF8,0xBD,0xF7,0xB5,0x8C,0xB0,0xAD,0x48,0x20,0x38,0x0B,0x90,
0x80,0x6F,0x07,0x79,0x83,0x79,0x5B,0x1E,0xDB,0xB2,0x01,0x93,0xAD,0x4B,0x1B,0x78,
0x8B,0x42,0x02,0xD2,0xAB,0x4B,0x19,0x70,0x04,0xE0,0xAA,0x4C,0x8B,0x42,0x01,0xD9,
0xFF,0x23,0x23,0x70,0x43,0x78,0x5B,0x00,0x05,0x93,0xB2,0x23,0xC3,0x5E,0x04,0x93,
0x9F,0x48,0x80,0x38,0xC4,0x7A,0x9B,0x48,0x03,0x46,0xDC,0x33,0x0A,0x93,0x91,0x23,
0x9B,0x00,0xC3,0x18,0x28,0x30,0x09,0x93,0x08,0x90,0x01,0x2C,0x20,0xD1,0x08,0x46,
0x0A,0x9B,0x78,0x43,0xC4,0x18,0x09,0x9B,0xC3,0x18,0x9C,0x46,0x08,0x9B,0xC0,0x18,
0x86,0x46,0x0C,0x98,0x00,0x23,0x11,0xE0,0x06,0x78,0x26,0x70,0x64,0x1C,0x06,0x78,
0x65,0x46,0x2E,0x70,0x06,0x78,0x75,0x46,0x80,0x1C,0x2E,0x70,0x65,0x46,0x6D,0x1C,
0xAC,0x46,0x75,0x46,0x6D,0x1C,0xAE,0x46,0x5B,0x1C,0x5B,0xB2,0xBB,0x42,0xEB,0xDB,
0x08,0x46,0x78,0x43,0x08,0x9B,0x07,0x90,0xC0,0x18,0x86,0x46,0x0C,0x98,0x84,0x46,
0x00,0x20,0x35,0xE0,0x63,0x46,0x1B,0x88,0x74,0x46,0x24,0x78,0xE3,0x1A,0x1B,0xB2,
0x05,0x9C,0xA3,0x42,0x02,0xDA,0x04,0x9C,0xA3,0x42,0x21,0xDC,0x01,0x24,0x8C,0x40,
0x13,0x68,0x55,0x68,0xE6,0x17,0x23,0x43,0x35,0x43,0x55,0x60,0x2C,0x46,0x13,0x60,
0x00,0x29,0x08,0xD0,0x25,0x46,0x4E,0x1E,0x01,0x24,0xB4,0x40,0xE6,0x17,0x23,0x43,
0x35,0x43,0x55,0x60,0x13,0x60,0x01,0x9B,0x99,0x42,0x09,0xD2,0x4E,0x1C,0x01,0x23,
0xB3,0x40,0x14,0x68,0x55,0x68,0xDE,0x17,0x1C,0x43,0x35,0x43,0x55,0x60,0x14,0x60,
0x73,0x46,0x5B,0x1C,0x9E,0x46,0x63,0x46,0x9B,0x1C,0x9C,0x46,0x40,0x1C,0x40,0xB2,
0xB8,0x42,0xC7,0xDB,0x07,0x99,0x0A,0x98,0x0D,0x18,0x07,0x99,0x09,0x98,0x0E,0x18,
0x0C,0x9C,0x0B,0x98,0x80,0x6F,0x80,0x30,0x00,0x7E,0x01,0x28,0x03,0xD1,0x65,0x49,
0x09,0x78,0xFF,0x29,0x02,0xD0,0x02,0x28,0x1D,0xD0,0x20,0xE0,0x00,0x23,0x16,0xE0,
0x00,0x22,0xA2,0x5E,0x28,0x78,0x31,0x78,0x30,0x70,0x2A,0x70,0x88,0x42,0x02,0xDD,
0x84,0x46,0x08,0x46,0x61,0x46,0x82,0x42,0x01,0xDC,0x20,0x80,0x02,0xE0,0x8A,0x42,
0x00,0xDB,0x21,0x80,0x6D,0x1C,0x76,0x1C,0xA4,0x1C,0x5B,0x1C,0x5B,0xB2,0xBB,0x42,
0xE6,0xDB,0x0F,0xB0,0x60,0xE4,0x53,0x48,0x00,0x78,0xFF,0x28,0x01,0xD0,0x00,0x20,
0x2D,0xE0,0x00,0x20,0x06,0x90,0x1E,0xE0,0x00,0x21,0x61,0x5E,0x03,0x91,0x28,0x78,
0x31,0x78,0x02,0x91,0x03,0x99,0x08,0x18,0x02,0x99,0x40,0x18,0x0B,0x99,0x4A,0x6C,
0x03,0x21,0x90,0x47,0x00,0xB2,0x30,0x70,0x76,0x1C,0x03,0x99,0x29,0x70,0x6D,0x1C,
0x02,0x99,0x4A,0x00,0x89,0x18,0x08,0x18,0x80,0x10,0x20,0x80,0xA4,0x1C,0x06,0x98,
0x40,0x1C,0x40,0xB2,0x06,0x90,0x06,0x98,0xB8,0x42,0xDD,0xDB,0xD1,0xE7,0x21,0x78,
0xA4,0x1C,0x29,0x70,0x6D,0x1C,0x31,0x70,0x76,0x1C,0x40,0x1C,0x40,0xB2,0xB8,0x42,
0xF5,0xDB,0xC6,0xE7,0xF0,0xB5,0x85,0xB0,0x31,0x4E,0x20,0x3E,0xB0,0x6F,0xC1,0x7A,
0x00,0x91,0x35,0x4C,0x04,0x94,0x1B,0x21,0x2A,0x48,0x89,0x01,0x47,0x18,0x35,0x21,
0x49,0x01,0x45,0x18,0x00,0x99,0x24,0x23,0x30,0x4A,0x59,0x43,0x08,0x18,0x80,0x18,
0x03,0x90,0x64,0xE0,0x20,0x78,0x0F,0x28,0x60,0xD0,0xE0,0x79,0x01,0x06,0x0F,0xD4,
0x02,0x28,0x19,0xD0,0xE8,0x7C,0x02,0x28,0x01,0xD2,0x20,0x20,0xA0,0x70,0xFF,0x20,
0x20,0x71,0x60,0x71,0xE0,0x78,0x79,0x7E,0x88,0x42,0x01,0xD8,0x00,0x20,0xE0,0x71,
0xE0,0x79,0x40,0x06,0x40,0x0E,0xE0,0x71,0x00,0x28,0x01,0xD0,0x40,0x1E,0xE0,0x71,
0xE0,0x79,0x00,0x28,0x3C,0xD0,0x41,0xE0,0x0E,0x20,0x20,0x5E,0x02,0x90,0x10,0x20,
0x20,0x5E,0x01,0x90,0x09,0x21,0x20,0x46,0x08,0xF0,0xA4,0xFA,0x0E,0x21,0x61,0x5E,
0x02,0x98,0x08,0x1A,0x00,0xD5,0x40,0x42,0x01,0xB2,0x10,0x22,0xA2,0x5E,0x01,0x98,
0x10,0x1A,0x00,0xD5,0x40,0x42,0x40,0x18,0x00,0xB2,0xB1,0x6F,0x80,0x31,0xC9,0x8D,
0x89,0x08,0x81,0x42,0xCB,0xDD,0x02,0x98,0xE0,0x81,0x01,0x98,0x20,0x82,0xC6,0xE7,
0x00,0x20,0x00,0x40,0x70,0x03,0x00,0x20,0xFF,0xFF,0x00,0x00,0x0E,0xD1,0x00,0x00,
0x90,0x0A,0x00,0x20,0x64,0x00,0x00,0x20,0x10,0x00,0x00,0x20,0x0C,0x00,0x00,0x20,
0x10,0x2E,0xFF,0xFF,0x00,0x00,0x00,0x20,0x3E,0x09,0x00,0x20,0xCE,0x05,0x00,0x00,
0x60,0x78,0x80,0x08,0x80,0x00,0x60,0x70,0x00,0x20,0xA0,0x70,0x24,0x34,0x03,0x98,
0xA0,0x42,0x97,0xD8,0x00,0x21,0x00,0x22,0xEA,0x74,0x04,0x98,0x10,0xE0,0x04,0x78,
0x00,0x9B,0x9C,0x42,0x0A,0xD2,0xC3,0x78,0x7C,0x7E,0x5B,0x06,0x5B,0x0E,0xA3,0x42,
0x04,0xD9,0x83,0x78,0x20,0x2B,0x01,0xD0,0x01,0x21,0x04,0xE0,0x82,0x70,0x24,0x30,
0x03,0x9B,0x83,0x42,0xEB,0xD8,0x00,0x29,0x2F,0xD0,0x04,0x98,0x2A,0xE0,0x82,0x70,
0x03,0x78,0x00,0x99,0x8B,0x42,0x24,0xD2,0xC1,0x78,0x7B,0x7E,0x49,0x06,0x49,0x0E,
0x99,0x42,0x1E,0xD9,0x01,0x21,0x81,0x70,0xE9,0x7C,0x49,0x1C,0xE9,0x74,0x0E,0x23,
0xC3,0x5E,0x00,0x2B,0x01,0xDA,0xC2,0x81,0x06,0xE0,0xB1,0x6F,0x80,0x31,0x0C,0x8C,
0xA3,0x42,0x01,0xDD,0x09,0x8C,0xC1,0x81,0x10,0x23,0xC3,0x5E,0x00,0x2B,0x01,0xDA,
0x02,0x82,0x06,0xE0,0xB1,0x6F,0x80,0x31,0x4C,0x8C,0xA3,0x42,0x01,0xDD,0x49,0x8C,
0x01,0x82,0x24,0x30,0x03,0x99,0x81,0x42,0xD1,0xD8,0x87,0xE5,0xF0,0xB5,0x80,0x4A,
0x93,0x6F,0x1C,0x7F,0x62,0x00,0xFF,0x28,0x2D,0xD0,0x24,0x25,0x68,0x43,0x7D,0x4D,
0x7D,0x4E,0x40,0x19,0x80,0x19,0x06,0x26,0x71,0x43,0x49,0x19,0x7A,0x4D,0x24,0x3D,
0x4E,0x19,0x14,0x25,0x45,0x5F,0x00,0x2D,0x00,0xDA,0x6D,0x42,0x16,0x21,0x41,0x5E,
0x00,0x29,0x00,0xDA,0x49,0x42,0x6D,0x18,0x74,0x49,0x8D,0x42,0x00,0xD3,0x00,0x25,
0x0E,0x27,0x31,0x88,0xC7,0x5F,0xC9,0x1B,0x00,0xD5,0x49,0x42,0x10,0x27,0x76,0x88,
0xC7,0x5F,0xF6,0x1B,0x00,0xD5,0x76,0x42,0x89,0x19,0x8C,0x42,0x2C,0xD8,0x84,0x79,
0x01,0x2C,0x02,0xD0,0x07,0xE0,0x00,0x20,0xF0,0xBD,0x2D,0x27,0xFF,0x5C,0xC6,0x79,
0x7F,0x1E,0xBE,0x42,0x1E,0xDB,0x62,0x4E,0xB6,0x6F,0x80,0x36,0x01,0x2C,0x08,0xD1,
0xDB,0x7E,0xAB,0x42,0x05,0xD3,0xC0,0x78,0x73,0x7B,0x98,0x42,0x01,0xD8,0x0A,0x28,
0x10,0xD2,0x01,0x2C,0x06,0xD1,0x91,0x42,0x04,0xD3,0x5D,0x4B,0x70,0x7B,0x1B,0x88,
0x98,0x42,0x07,0xD2,0x01,0x2C,0x02,0xD1,0x50,0x00,0x88,0x42,0x02,0xD9,0x90,0x00,
0x88,0x42,0x01,0xD8,0x00,0x20,0xF0,0xBD,0x01,0x20,0xF0,0xBD,0xF0,0xB5,0x85,0xB0,
0x54,0x49,0x4F,0x48,0x40,0x30,0x80,0x78,0x05,0x28,0x7D,0xD0,0x52,0x4D,0xA8,0x1D,
0x01,0x90,0x80,0x1D,0x00,0x90,0x00,0x20,0x49,0x4A,0x04,0x92,0xFF,0x22,0x0F,0x23,
0x07,0xE0,0x2A,0x54,0xCC,0x79,0x00,0x2C,0x00,0xD1,0x0B,0x70,0x40,0x1C,0xC0,0xB2,
0x24,0x31,0x04,0x9C,0xA4,0x6F,0xE4,0x7A,0x84,0x42,0xF2,0xD8,0x00,0x27,0x40,0x4E,
0x60,0x3E,0xF0,0x7B,0x00,0x28,0x49,0xD0,0x2A,0x46,0x03,0xA9,0x00,0x98,0x08,0xF0,
0x19,0xFD,0x07,0x46,0x38,0x00,0x0A,0xD0,0x01,0x2F,0x15,0xD0,0x68,0x46,0x02,0x7B,
0xF3,0x7B,0x01,0x99,0x00,0x98,0x08,0xF0,0x1B,0xFC,0x00,0x24,0x33,0xE0,0x00,0x24,
0x06,0xE0,0x22,0x46,0xFF,0x21,0x01,0x20,0x08,0xF0,0x00,0xFB,0x64,0x1C,0xE4,0xB2,
0xF0,0x7B,0xA0,0x42,0xF5,0xD8,0x29,0xE0,0x2C,0x78,0x00,0x21,0x20,0x46,0xFF,0xF7,
0x55,0xFF,0x00,0x28,0x01,0xD0,0x00,0x20,0x00,0xE0,0x01,0x20,0x00,0x22,0x21,0x46,
0x08,0xF0,0xEC,0xFA,0x1A,0xE0,0x01,0x98,0x00,0x5D,0xFF,0x28,0x02,0xD0,0x28,0x5C,
0x02,0x90,0x01,0xE0,0xFF,0x20,0x02,0x90,0x21,0x46,0x02,0x98,0xFF,0xF7,0x3E,0xFF,
0x00,0x28,0x01,0xD0,0x00,0x20,0x00,0xE0,0x01,0x20,0x22,0x46,0x02,0x99,0x08,0xF0,
0xD5,0xFA,0x64,0x1C,0xE4,0xB2,0xF0,0x7B,0xA0,0x42,0xE4,0xD8,0x38,0x46,0xFF,0xF7,
0x61,0xFE,0xF0,0x7B,0x1A,0x4C,0x00,0x28,0x06,0xD1,0x20,0x88,0x7D,0x21,0xC9,0x00,
0x88,0x42,0x01,0xD2,0x40,0x1C,0x20,0x80,0xF0,0x7C,0x00,0x28,0x04,0xD0,0x00,0x22,
0x00,0x20,0x10,0x4D,0x17,0x26,0x00,0xE0,0x16,0xE0,0x04,0x99,0xB6,0x01,0x89,0x6F,
0xCB,0x7A,0x0B,0xE0,0x24,0x21,0x41,0x43,0x49,0x19,0x89,0x19,0x0F,0x7C,0x01,0x2F,
0x02,0xD1,0xC9,0x7B,0x03,0x29,0x08,0xD0,0x40,0x1C,0xC0,0xB2,0x83,0x42,0xF1,0xD8,
0x00,0x2A,0x01,0xD1,0x00,0x20,0x20,0x80,0x88,0xE4,0x52,0x1C,0xD2,0xB2,0xF7,0xE7,
0x70,0x0A,0x00,0x20,0x70,0x03,0x00,0x20,0xCE,0x05,0x00,0x00,0xFF,0xFF,0x00,0x00,
0x06,0x00,0x00,0x20,0x3E,0x09,0x00,0x20,0x68,0x06,0x00,0x20,0x00,0x22,0x03,0x09,
0x8B,0x42,0x2C,0xD3,0x03,0x0A,0x8B,0x42,0x11,0xD3,0x00,0x23,0x9C,0x46,0x4E,0xE0,
0x03,0x46,0x0B,0x43,0x3C,0xD4,0x00,0x22,0x43,0x08,0x8B,0x42,0x31,0xD3,0x03,0x09,
0x8B,0x42,0x1C,0xD3,0x03,0x0A,0x8B,0x42,0x01,0xD3,0x94,0x46,0x3F,0xE0,0xC3,0x09,
0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41,0x83,0x09,0x8B,0x42,0x01,0xD3,
0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42,0x01,0xD3,0x4B,0x01,0xC0,0x1A,
0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01,0xC0,0x1A,0x52,0x41,0xC3,0x08,
0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41,0x83,0x08,0x8B,0x42,0x01,0xD3,
0x8B,0x00,0xC0,0x1A,0x52,0x41,0x43,0x08,0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A,
0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46,0x52,0x41,0x10,0x46,0x70,0x47,0x5D,0xE0,
0xCA,0x0F,0x00,0xD0,0x49,0x42,0x03,0x10,0x00,0xD3,0x40,0x42,0x53,0x40,0x00,0x22,
0x9C,0x46,0x03,0x09,0x8B,0x42,0x2D,0xD3,0x03,0x0A,0x8B,0x42,0x12,0xD3,0xFC,0x22,
0x89,0x01,0x12,0xBA,0x03,0x0A,0x8B,0x42,0x0C,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42,
0x08,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42,0x04,0xD3,0x89,0x01,0x3A,0xD0,0x92,0x11,
0x00,0xE0,0x89,0x09,0xC3,0x09,0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41,
0x83,0x09,0x8B,0x42,0x01,0xD3,0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42,
0x01,0xD3,0x4B,0x01,0xC0,0x1A,0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01,
0xC0,0x1A,0x52,0x41,0xC3,0x08,0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41,
0x83,0x08,0x8B,0x42,0x01,0xD3,0x8B,0x00,0xC0,0x1A,0x52,0x41,0xD9,0xD2,0x43,0x08,
0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A,0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46,
0x63,0x46,0x52,0x41,0x5B,0x10,0x10,0x46,0x01,0xD3,0x40,0x42,0x00,0x2B,0x00,0xD5,
0x49,0x42,0x70,0x47,0x63,0x46,0x5B,0x10,0x00,0xD3,0x40,0x42,0x01,0xB5,0x00,0x20,
0xC0,0x46,0xC0,0x46,0x02,0xBD,0x75,0x46,0x00,0xF0,0x22,0xF8,0xAE,0x46,0x05,0x00,
0x69,0x46,0x53,0x46,0xC0,0x08,0xC0,0x00,0x85,0x46,0x18,0xB0,0x20,0xB5,0xFE,0xF7,
0x87,0xFF,0x60,0xBC,0x00,0x27,0x49,0x08,0xB6,0x46,0x00,0x26,0xC0,0xC5,0xC0,0xC5,
0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0x40,0x3D,0x49,0x00,
0x8D,0x46,0x70,0x47,0x04,0x46,0xC0,0x46,0xC0,0x46,0x20,0x46,0xFE,0xF7,0xDD,0xFD,
0x00,0x48,0x70,0x47,0x70,0x00,0x00,0x20,0x01,0x49,0x18,0x20,0xAB,0xBE,0xFE,0xE7,
0x26,0x00,0x02,0x00,0x70,0x47,0x00,0x00,0x23,0x0B,0x28,0x0C,0x0A,0x0A,0x0C,0x00,
0x02,0x02,0x40,0x06,0x00,0x00,0x00,0x01,0x08,0x08,0x10,0x85,0x1C,0x0E,0x07,0x03,
0x0A,0x1E,0x64,0x21,0x42,0x42,0x08,0x02,0x16,0x00,0x00,0x00,0x10,0x06,0x02,0x00,
0x06,0x04,0x14,0x14,0x0A,0x05,0x28,0x1E,0x3C,0x64,0x02,0x04,0x08,0x01,0x02,0x04,
0x04,0x02,0x01,0x08,0x01,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x04,0x02,0x01,0x08,0x04,0x02,0x01,0x08,0x04,0x02,0x01,0x01,0x01,0x01,
0xD8,0xE2,0xF6,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x02,0x04,0x03,0x08,0x09,
0x09,0x00,0x3C,0x0A,0x01,0x02,0x02,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3C,
0x3C,0x50,0x00,0x14,0xC8,0x14,0x00,0x01,0x84,0x04,0x02,0x02,0x5A,0x00,0x5A,0x01,
0x02,0x06,0x01,0x01,0x00,0x00,0x00,0x00,0xE0,0x01,0x20,0x03,0xBE,0x00,0x09,0x00,
0x90,0x01,0x01,0x01,0x00,0x01,0x20,0x00,0x00,0x00,0xF5,0xFF,0x52,0x01,0x92,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0xAA,0x42,0x00,0x00,
0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x15,0x10,0x00,0x40,
0x15,0x10,0x00,0x40,0x15,0x10,0x00,0x40,0x25,0x10,0x00,0x40,0x25,0x10,0x00,0x40,
0x25,0x10,0x00,0x40,0x21,0x10,0x00,0x40,0x19,0x10,0x00,0x40,0x15,0x10,0x00,0x40,
0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,
0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,
0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,
0x21,0x10,0x00,0x40,0x21,0x10,0x00,0x40,0x21,0x10,0x00,0x40,0x1D,0x10,0x00,0x40,
0x1D,0x10,0x00,0x40,0x1D,0x10,0x00,0x40,0x1D,0x10,0x00,0x40,0x19,0x10,0x00,0x40,
0x19,0x10,0x00,0x40,0x19,0x10,0x00,0x40,0x60,0x10,0x00,0x40,0x5C,0x10,0x00,0x40,
0x58,0x10,0x00,0x40,0x54,0x10,0x00,0x40,0x50,0x10,0x00,0x40,0x4C,0x10,0x00,0x40,
0x48,0x10,0x00,0x40,0x44,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x64,0x10,0x00,0x40,
0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,
0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,
0x44,0x10,0x00,0x40,0x48,0x10,0x00,0x40,0x4C,0x10,0x00,0x40,0x50,0x10,0x00,0x40,
0x54,0x10,0x00,0x40,0x58,0x10,0x00,0x40,0x48,0x10,0x00,0x40,0x44,0x10,0x00,0x40,
0x40,0x10,0x00,0x40,0x64,0x10,0x00,0x40,0x60,0x10,0x00,0x40,0x5C,0x10,0x00,0x40,
0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,
0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,
0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,
0xFF,0xFF,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0xFF,0x00,0xFF,
0xFF,0xFF,0xFF,0x00,0xFF,0x01,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x76,0xA5,0x18,0xA7,0x23,0xA1,0x45,0x63,0x65,0x07,0x56,0xAA,
0x78,0xA1,0x21,0x00,0x00,0x00,0x00,0x00,0x21,0xAA,0x43,0xAA,0x56,0xAA,0x81,0xA7,
0x21,0x00,0x67,0xAA,0x23,0xAA,0x87,0xAA,0x32,0xAA,0x87,0xAA,0x32,0xAA,0x87,0xAA,
0x32,0xAA,0x87,0xA1,0x71,0x06,0x87,0xAA,0x23,0xAA,0x87,0xAA,0x32,0xAA,0x00,0x00,
0x87,0xAA,0x23,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xAA,0x87,0xAA,0x51,0xA6,
0x47,0x06,0x45,0x00,0x28,0xA1,0x76,0xAA,0x12,0xA8,0x00,0x00,0x00,0x00,0x34,0xAA,
0x56,0xAA,0x78,0xA1,0x21,0x00,0x00,0x00,0x67,0xAA,0x23,0xAA,0xA1,0xAA,0x87,0xAA,
0x32,0xAA,0x67,0xAA,0x23,0xAA,0x87,0xAA,0x32,0xAA,0xA1,0xAA,0x21,0xAA,0x56,0xAA,
0x81,0xA7,0x21,0xAA,0x00,0x00,0x34,0xAA,0x65,0xAA,0x87,0xAA,0x51,0x46,0x47,0x03,
0xA8,0xAA,0x21,0xAA,0x43,0xAA,0x56,0xAA,0x81,0xA7,0x34,0xAA,0x76,0xA5,0x18,0xA7,
0x23,0xA1,0x45,0xA3,0x23,0xA4,0x21,0xA8,0x87,0xA6,0x32,0xA4,0x78,0x21,0x76,0xA5,
0x23,0xA1,0x45,0x63,0x65,0x07,0x00,0x00,0x01,0x00,0x00,0xFF,0xFF,0x00,0x00,0x01,
0x02,0x02,0x02,0x01,0x02,0x02,0x01,0x01,0x01,0x02,0x01,0x02,0x01,0x02,0x02,0x02,
0x01,0x01,0x02,0x02,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
0x02,0x02,0x02,0x02,0xFC,0x1D,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x00,0x00,0x00,
0x98,0x00,0x00,0x00,0x0C,0x1E,0x00,0x00,0x10,0x00,0x00,0x20,0xE0,0x0A,0x00,0x00,
0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x5B,0x5A,0x35,0x35,0xA5,0xA5,0xCA,0xCA,0x88,0x77,0x66,0x55,
0x44,0x33,0x22,0x11,0x0C,0x00,0x0A,0x00,0xE0,0x01,0x20,0x03,0xEE,0x2F,0xCA,0xCA,
0x02,0x03,0x00,0x00,0x11,0x18,0xA8,0x00,0x01,0x00,0x00,0x01,0xE5,0xFE,0xCA,0x8A,
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,663 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst36xxes_fw.h
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef HYNITRON_FIRMWARE_H
#define HYNITRON_FIRMWARE_H
static const uint8_t fw_bin[] = {
0x80,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x01,0x00,0x54,0x00,0x01,0x00,
0x80,0x00,0x01,0x00,0xAC,0x00,0x01,0x00,0xD8,0x00,0x01,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,
0x05,0x23,0xCA,0xCA,0x0A,0xA5,0xCA,0xCA,0x10,0x27,0xCA,0xCA,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x0A,0x00,0xD0,0x02,0x00,0x05,
0x00,0x00,0x00,0x00,0x62,0x47,0x00,0x00,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
0x22,0x14,0x00,0x00,0x44,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
0x0C,0x0D,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,
0x1D,0x1E,0x1F,0x20,0x21,0x22,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,
0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x00,0x00,0x0A,0x00,0x00,0x00,
0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x3A,0x43,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x00,0x00,0x00,0x0A,0x1E,0x1E,0x14,
0x05,0x0A,0x20,0x28,0x3C,0x14,0x19,0x1E,0x2D,0x33,0x37,0x37,0x0A,0x08,0x0F,0x5A,
0x28,0x32,0x64,0x01,0x01,0x08,0x14,0x05,0x1E,0x0A,0x5F,0x14,0x32,0x96,0x03,0x5A,
0x03,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x01,0x00,0x80,0x0A,0x28,0x02,0x00,
0x20,0x03,0x00,0x00,0x00,0x5B,0x02,0x03,0x02,0x37,0x00,0x00,0x00,0x04,0x01,0x00,
0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00,0x01,0x11,0x00,0x00,
0x64,0x00,0x02,0x01,0x01,0x30,0x00,0x00,0x14,0x28,0xD8,0x28,0x03,0x03,0x28,0x14,
0x50,0xB0,0x28,0x03,0x03,0x32,0x14,0x28,0xD8,0x28,0x03,0x03,0x32,0x00,0x00,0x00,
0xE8,0x03,0x02,0x00,0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x00,0x42,0x25,0x0D,0x70,
0x73,0x67,0x1E,0x00,0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x30,0x00,0x46,0x73,0x67,
0x04,0x0F,0x70,0x14,0xC8,0x00,0x00,0x01,0x20,0x01,0x03,0x50,0x28,0x14,0xC8,0x00,
0x20,0x01,0x01,0x08,0x04,0x03,0x0F,0x16,0x23,0x33,0x11,0x19,0x2A,0x44,0x13,0x1F,
0x2F,0x55,0x0F,0x13,0x21,0x0F,0x17,0x28,0x0F,0x1C,0x30,0x11,0x1A,0x23,0x28,0x34,
0x4D,0x64,0x01,0x14,0x70,0x10,0x00,0x32,0x41,0xA3,0x46,0xA3,0x4F,0x10,0x80,0x33,
0x77,0x43,0x89,0x74,0x43,0xAB,0x00,0x33,0x2D,0x10,0x4E,0x10,0x8C,0x60,0x0E,0x10,
0x84,0x64,0x0C,0x60,0x07,0x08,0x6D,0x10,0x4D,0x10,0x00,0x31,0xC8,0x64,0x06,0x08,
0x3C,0x78,0x00,0x90,0x00,0xB2,0x03,0x23,0xF1,0x07,0x20,0xB3,0x03,0x23,0xF7,0x07,
0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x40,0x09,0x00,0x00,0x00,0x00,0x28,0x00,0x00,
0x00,0x28,0x00,0x00,0x30,0x19,0x00,0x00,0x00,0x28,0x00,0x00,0x2C,0x56,0x00,0x00,
0x05,0x10,0x00,0xC0,0x20,0x64,0x25,0x10,0x87,0x6F,0xFF,0xE3,0xCD,0xFF,0x00,0xE0,
0x8B,0x01,0x00,0x04,0x00,0x01,0x00,0x80,0x7C,0x5F,0x00,0x00,0x00,0x30,0x3C,0x78,
0x3C,0x78,0xA5,0x30,0x3C,0x78,0x3C,0x78,0xD4,0x14,0xB0,0x02,0x70,0x85,0x40,0x3B,
0x13,0x08,0x20,0x37,0xD4,0x61,0x6F,0x87,0x40,0x3B,0x9F,0x6D,0x0D,0x08,0x94,0x02,
0x60,0x94,0x0B,0x93,0xC1,0x7B,0x65,0x87,0x40,0x3B,0x07,0x0C,0x40,0x38,0x07,0x08,
0x76,0x85,0x00,0x23,0x76,0xA5,0x94,0x14,0x40,0x38,0xFE,0x0F,0x60,0x94,0x6A,0x93,
0xCD,0x7B,0x60,0x94,0x07,0x93,0xC1,0x7B,0x40,0x38,0xF6,0x0F,0x00,0x33,0x00,0x2B,
0x6A,0xA6,0xF2,0x07,0xC2,0x14,0x41,0x03,0x6A,0x82,0x30,0x31,0xC4,0x64,0x17,0x0C,
0x59,0x3B,0x17,0x08,0x87,0x03,0x20,0x33,0xD0,0x60,0x32,0x83,0x01,0x49,0x43,0x6D,
0xA5,0x3D,0xB3,0xA3,0xBF,0x84,0xF0,0x34,0x16,0x65,0x05,0x08,0x00,0x34,0x5F,0x2C,
0x10,0x6C,0x13,0xA3,0x00,0x21,0x32,0xA3,0x6D,0x03,0x63,0xB2,0x00,0x30,0x82,0x14,
0x01,0x30,0xFE,0x07,0xD4,0x14,0x39,0x14,0x70,0x03,0x80,0x37,0x63,0xB8,0x60,0x93,
0x05,0x1C,0xDC,0x60,0x43,0x6D,0x67,0x93,0x10,0x32,0x33,0x03,0x13,0x6C,0xCD,0x7B,
0x10,0x33,0xD0,0x60,0x8F,0x6D,0x77,0x03,0x10,0x32,0x60,0x93,0xDC,0x60,0x67,0x93,
0x38,0x03,0x1B,0x6C,0xCD,0x7B,0x2B,0x33,0xD6,0x64,0x30,0x08,0xBA,0x03,0x7F,0x33,
0x23,0x85,0x4C,0x68,0x0C,0x84,0x2D,0xA4,0x00,0xE0,0xE0,0x07,0x63,0x85,0xCE,0x74,
0xDF,0x3B,0x7A,0x13,0x5F,0x03,0x60,0x93,0x64,0x93,0x17,0x08,0x13,0x6C,0x00,0x31,
0xCD,0x7B,0x5E,0x13,0x21,0x82,0x60,0x82,0xC4,0x7C,0x02,0x84,0x26,0x84,0x9C,0x13,
0xCD,0x74,0x90,0x60,0x00,0xE0,0x95,0x07,0x76,0x13,0x01,0x32,0x42,0xA3,0x00,0x32,
0x03,0x2A,0x41,0xA3,0x19,0x14,0x94,0x14,0x01,0x31,0x13,0x6C,0xCD,0x7B,0x97,0x6C,
0x64,0x85,0x26,0x84,0x02,0x84,0x17,0x22,0xEE,0x07,0x2C,0x33,0xD6,0x64,0x22,0x08,
0x8C,0x13,0x63,0x84,0x40,0x3B,0x12,0x08,0xF2,0x32,0x8C,0x13,0x44,0x42,0x20,0x84,
0x90,0x60,0x03,0x94,0x00,0xE0,0xB4,0x06,0x40,0x84,0x41,0x42,0x66,0x13,0x8C,0x60,
0x21,0x84,0x04,0x94,0x00,0xE0,0xAC,0x06,0xD8,0x07,0x24,0x84,0x42,0x13,0x04,0x94,
0x00,0xE0,0xA6,0x06,0x44,0x84,0x41,0x42,0x7F,0x12,0x8C,0x60,0x25,0x84,0x05,0x94,
0xF2,0x07,0x2D,0x33,0xD6,0x64,0x9D,0x08,0x7A,0x12,0x43,0x83,0x40,0x3A,0x5D,0x12,
0x43,0xB8,0x59,0x08,0x60,0x92,0x01,0x32,0xB8,0x12,0xDC,0x60,0x42,0xB8,0x40,0x85,
0x41,0xB8,0x59,0x12,0x94,0x60,0x40,0xB8,0x6D,0x93,0x64,0xB8,0x77,0x12,0x43,0xB8,
0xD4,0x60,0x41,0x95,0x23,0x95,0x1B,0x6C,0xC4,0x98,0xD9,0x7B,0x74,0x12,0x26,0x83,
0x70,0x12,0x00,0x32,0x60,0x93,0xDC,0x60,0x6E,0x93,0x16,0x84,0xCD,0x7B,0x03,0x6D,
0x00,0xE0,0x66,0x06,0x00,0x30,0x00,0xE0,0x18,0x07,0x6A,0x12,0x60,0x93,0xDC,0x60,
0x6F,0x93,0xCD,0x7B,0x67,0x12,0x60,0x93,0xDC,0x60,0x71,0x93,0xCD,0x7B,0x7E,0x11,
0xF2,0x30,0x60,0x93,0x40,0x85,0xDC,0x60,0x24,0x12,0x04,0x40,0x54,0x60,0x41,0x42,
0x67,0x93,0x14,0x60,0xCD,0x7B,0x75,0x11,0xF2,0x30,0x60,0x93,0x04,0x40,0x40,0x85,
0xC3,0x93,0x53,0x6C,0x63,0x98,0x14,0x60,0xD9,0x7B,0x01,0x31,0x00,0x30,0x00,0xE0,
0x91,0x07,0x01,0x31,0x01,0x30,0x00,0xE0,0x8D,0x07,0x00,0x85,0x72,0x11,0x01,0x40,
0x0C,0x60,0x6A,0x11,0x41,0x85,0x60,0x93,0xC3,0x93,0x76,0x11,0xD4,0x60,0x53,0x6C,
0xD9,0x7B,0x6B,0x07,0xAE,0x5B,0x17,0x23,0x63,0xB8,0x01,0x32,0x6D,0x11,0x1B,0x6C,
0x60,0x93,0x42,0xB8,0x40,0x85,0x41,0xB8,0x43,0x98,0x40,0xB8,0xDC,0x60,0x6D,0x93,
0x64,0xB8,0x23,0x95,0xCB,0x6C,0xC4,0x98,0x41,0x95,0xD9,0x7B,0x65,0x11,0x32,0x84,
0x60,0x93,0xDC,0x60,0x00,0x32,0x6E,0x93,0x16,0x84,0xCD,0x7B,0x03,0x6D,0x00,0xE0,
0x0F,0x06,0x00,0x30,0x00,0xE0,0xC1,0x06,0x7E,0x10,0x60,0x93,0xDC,0x60,0x6F,0x93,
0xCD,0x7B,0x7C,0x10,0x60,0x93,0xDC,0x60,0x71,0x93,0xCD,0x7B,0x72,0x10,0x40,0x85,
0x60,0x93,0xDC,0x60,0x23,0x98,0x41,0x42,0x67,0x93,0x13,0x10,0xCD,0x7B,0x6B,0x10,
0x40,0x85,0x60,0x93,0xA3,0x93,0x53,0x6C,0x63,0x98,0x0F,0x10,0xD5,0x7B,0x2D,0x07,
0x2E,0x33,0xD6,0x64,0x30,0x0B,0x67,0x31,0x73,0x30,0x00,0xE0,0xEF,0x06,0x6A,0x10,
0x00,0xAB,0x23,0x07,0xD4,0x51,0x00,0x00,0xD0,0x51,0x00,0x00,0x00,0x28,0x00,0x00,
0x07,0x52,0x00,0x00,0xE4,0x54,0x00,0x00,0x50,0x17,0x00,0x00,0x60,0x17,0x00,0x00,
0x10,0x28,0x00,0x00,0x14,0x4C,0x00,0x00,0xF4,0x3C,0x00,0x00,0xEE,0x0A,0x00,0x00,
0x14,0x3C,0x00,0x00,0x0C,0x0F,0x00,0x00,0xBA,0x0E,0x00,0x00,0xF4,0x51,0x00,0x00,
0x98,0x0E,0x00,0x00,0xD4,0x14,0x2E,0x16,0x6E,0x01,0x4D,0x01,0xCD,0x01,0x2C,0x01,
0x0C,0x01,0x33,0x20,0x60,0xB2,0x4C,0x01,0x40,0xB6,0x4C,0x01,0x40,0xB1,0x60,0x93,
0x00,0x31,0xCD,0x7B,0x71,0x01,0x37,0x23,0x63,0xB8,0x60,0x96,0x80,0x93,0x00,0x31,
0x63,0x98,0x12,0x1F,0x52,0x01,0x11,0x01,0xD1,0x7B,0x71,0x01,0x81,0xEA,0x52,0x01,
0x37,0xAB,0x52,0x01,0x81,0xEA,0x51,0x01,0x45,0xB3,0x38,0xAB,0x57,0x22,0x20,0x31,
0x4C,0x60,0x4F,0xB3,0x30,0x30,0x60,0x02,0x97,0x01,0xB6,0x01,0x14,0x32,0x60,0x93,
0x12,0xA1,0x7F,0x23,0x53,0x6C,0x67,0x93,0x17,0x6C,0xCD,0x7B,0x16,0x33,0xD0,0x60,
0x66,0xB5,0x38,0x33,0xD0,0x60,0x67,0xB5,0x4C,0x33,0xD0,0x60,0x68,0xB5,0x65,0xB8,
0x7F,0x01,0xD0,0x60,0x69,0xB5,0x7F,0x01,0xD0,0x60,0x6A,0xB5,0x60,0x02,0xD0,0x60,
0x6B,0xB5,0x60,0x02,0xD0,0x60,0x6C,0xB5,0x66,0xB8,0x61,0x02,0xD0,0x60,0x6D,0xB5,
0x62,0x02,0xD0,0x60,0x6E,0xB5,0x62,0x02,0xD0,0x60,0x6F,0xB5,0x63,0x02,0xD0,0x60,
0x70,0xB5,0x67,0xB8,0x64,0x02,0xD0,0x60,0x71,0xB5,0x64,0x02,0xD0,0x60,0x72,0xB5,
0x65,0x02,0xD0,0x60,0x73,0xB5,0xF2,0x33,0x64,0x43,0xD0,0x60,0x74,0xB5,0x67,0x02,
0xD0,0x60,0x75,0xB5,0x68,0x02,0xD0,0x60,0x76,0xB5,0xA4,0xB7,0x29,0x02,0x7F,0x02,
0x9B,0x23,0x61,0xB7,0x77,0x21,0x61,0x03,0xD3,0x23,0x62,0xB7,0x1F,0x6C,0x6C,0x02,
0x44,0x03,0x63,0xB7,0x00,0x33,0x65,0xB7,0x6E,0x02,0x66,0xB7,0x67,0x03,0x0F,0x23,
0x67,0xB7,0x6F,0x02,0x68,0xB7,0x6F,0x02,0x69,0xB7,0xA2,0x33,0x61,0x43,0xC8,0x60,
0x6A,0xB7,0x76,0x02,0x6B,0xB7,0x72,0x02,0x6C,0xB7,0x78,0x02,0x17,0x23,0x4D,0xB7,
0x43,0x98,0x64,0xB8,0x6E,0xB7,0x75,0x02,0x65,0xB2,0x75,0x02,0x66,0xB1,0x75,0x02,
0x62,0xB1,0x75,0x03,0x60,0x93,0x61,0x93,0xCD,0x7B,0x20,0x32,0x7F,0x02,0x41,0xA3,
0x60,0x96,0x69,0x93,0xCD,0x7B,0x00,0x33,0x7F,0x2B,0x5B,0x02,0x64,0xA2,0x10,0x32,
0x64,0x03,0x00,0x31,0x40,0xA3,0x20,0x32,0x41,0xA3,0x60,0x96,0x68,0x93,0x04,0x30,
0xCD,0x7B,0x00,0x32,0x69,0x03,0x00,0x2A,0x5F,0xA3,0x0A,0x32,0x02,0xA3,0x5E,0xA3,
0x1F,0x23,0x0F,0x32,0x46,0xA3,0x01,0x32,0x47,0xA3,0x02,0x32,0x51,0xA3,0x01,0x32,
0x44,0xA3,0x63,0xB8,0x60,0x96,0x11,0x31,0x01,0x30,0x01,0x32,0x6B,0x93,0xCD,0x7B,
0x72,0x13,0x60,0x93,0x78,0x93,0xCD,0x7B,0x64,0x98,0x4E,0xD8,0x0A,0x10,0x48,0xAB,
0x4E,0xD8,0x0C,0x10,0x4C,0xAB,0x4E,0xD8,0x0E,0x10,0x50,0xAB,0x6B,0x13,0x60,0x93,
0x62,0x93,0xCD,0x7B,0x67,0x13,0x14,0x32,0x60,0x93,0x7F,0x23,0x57,0x6C,0x67,0x93,
0x13,0x6C,0xCD,0x7B,0x74,0x85,0x74,0xA4,0x75,0x85,0x75,0xA4,0xC8,0x31,0x60,0x96,
0x68,0x93,0x22,0x41,0x00,0x30,0xCD,0x7B,0x60,0x96,0x45,0x98,0x40,0xB8,0x7F,0x23,
0x78,0x93,0xA0,0x32,0x8A,0x35,0x64,0xB8,0xA1,0x45,0x37,0x13,0x41,0x42,0x16,0x13,
0x84,0x60,0x14,0x60,0x53,0x6C,0x71,0x13,0xA4,0x98,0xD5,0x7B,0x70,0x13,0x1E,0x83,
0x60,0x96,0x6A,0x93,0x00,0x31,0xCD,0x7B,0x00,0x33,0x6E,0xB8,0x5F,0x6C,0x73,0x12,
0x0E,0x18,0x60,0x93,0x5D,0x93,0x50,0xB8,0x5E,0x93,0x79,0x93,0x6F,0xB8,0x51,0xB8,
0x6F,0x13,0x47,0x13,0x2B,0x22,0x60,0xB7,0x6E,0x13,0x62,0xB7,0x6E,0x13,0x63,0xB7,
0x6E,0x13,0x61,0xB7,0x60,0x96,0x41,0xB8,0x00,0x32,0x40,0xB8,0xD0,0x32,0xBD,0x93,
0x48,0x42,0x30,0x33,0xD5,0x7B,0x00,0x32,0x60,0x96,0x42,0xB8,0x5B,0x32,0x41,0xB8,
0x37,0x32,0x40,0xB8,0xBB,0x93,0x03,0x32,0x02,0x33,0x02,0x31,0x00,0x30,0xD5,0x7B,
0x60,0x96,0x02,0x30,0x22,0x13,0xBD,0x11,0x64,0x93,0xCD,0x7B,0x61,0x13,0x09,0x32,
0x47,0xA3,0x41,0x83,0xA0,0x3A,0x41,0xA3,0x60,0x96,0x61,0x93,0xCD,0x7B,0x22,0x33,
0x75,0xA4,0x14,0x33,0x74,0xA4,0x90,0x30,0x72,0x11,0x05,0x40,0x60,0x93,0x5C,0x93,
0x40,0xB7,0x59,0x12,0x41,0xB7,0x5E,0x93,0x42,0xB7,0x58,0x12,0x43,0xB7,0x5F,0x93,
0x44,0xB7,0x57,0x12,0x45,0xB7,0x80,0x32,0x8C,0x60,0x20,0x92,0x42,0x92,0x48,0xB7,
0x26,0xB7,0x54,0x12,0x34,0x12,0x49,0xB7,0x4A,0x93,0x4A,0xB7,0x27,0xB7,0x5F,0x6C,
0x52,0x12,0x4B,0xB7,0x4B,0x93,0x4C,0xB7,0x51,0x12,0x4D,0xB7,0x4C,0x93,0x4E,0xB7,
0x50,0x12,0x4F,0xB7,0x53,0x93,0x50,0xB7,0x4F,0x12,0x51,0xB7,0x4E,0x93,0x52,0xB7,
0x4E,0x12,0x53,0xB7,0x52,0x93,0x54,0xB7,0x4D,0x12,0x55,0xB7,0x5A,0x93,0x56,0xB7,
0x4C,0x12,0x57,0xB7,0x5B,0x93,0x58,0xB7,0x4B,0x12,0x59,0xB7,0x55,0x93,0x76,0x93,
0x7C,0xB7,0x5A,0xB7,0x69,0x12,0x4A,0x12,0x7D,0xB7,0x5B,0xB7,0x03,0x32,0x69,0x12,
0x7E,0xB7,0x69,0x12,0x7F,0xB7,0x71,0x10,0x60,0x93,0x41,0xB8,0x00,0x32,0x40,0xB8,
0x8D,0x93,0x10,0x32,0x00,0x33,0xD1,0x7B,0x6A,0x10,0x85,0x11,0xC4,0xB8,0x69,0xB8,
0x64,0x11,0x65,0xB8,0x60,0x11,0x68,0xB8,0x64,0x11,0x67,0xB8,0x68,0x98,0x97,0x23,
0x6A,0xB8,0x67,0x98,0xFF,0x23,0x6B,0xB8,0x60,0x84,0x77,0x04,0x04,0x01,0x01,0x00,
0xE4,0x54,0x00,0x00,0x14,0x3C,0x00,0x00,0xD0,0x51,0x00,0x00,0x00,0x28,0x00,0x00,
0xB8,0x01,0x01,0x00,0xC8,0x02,0x01,0x00,0x18,0x3C,0x00,0x00,0xE0,0x3B,0x00,0x00,
0x98,0x3C,0x00,0x00,0x70,0x17,0x00,0x00,0xF4,0x3C,0x00,0x00,0x88,0x54,0x00,0x00,
0x9C,0x05,0x00,0x00,0x9E,0x05,0x00,0x00,0xEE,0x0A,0x00,0x00,0x0E,0x0E,0x00,0x00,
0x52,0x0E,0x00,0x00,0x54,0x0E,0x00,0x00,0x98,0x0E,0x00,0x00,0xBA,0x0E,0x00,0x00,
0xE2,0x0E,0x00,0x00,0xE4,0x0E,0x00,0x00,0x0C,0x0F,0x00,0x00,0x70,0x14,0x00,0x00,
0xB4,0x14,0x00,0x00,0x44,0x3B,0x00,0x00,0x08,0x52,0x00,0x00,0xD4,0x51,0x00,0x00,
0x7C,0x54,0x00,0x00,0xC0,0x00,0x00,0x00,0xE8,0x54,0x00,0x00,0xD4,0x0F,0x00,0x00,
0xF4,0x02,0x00,0x00,0x34,0x03,0x00,0x00,0x00,0x03,0x00,0x40,0x9C,0x02,0x00,0x00,
0xA0,0x02,0x00,0x00,0xA2,0x02,0x00,0x00,0xA6,0x02,0x00,0x00,0x98,0x0E,0x00,0x00,
0x00,0x20,0x00,0x40,0xFE,0x18,0x00,0x00,0x01,0x19,0x00,0x00,0x04,0x19,0x00,0x00,
0x0A,0x19,0x00,0x00,0x07,0x19,0x00,0x00,0x0D,0x19,0x00,0x00,0x10,0x19,0x00,0x00,
0x13,0x19,0x00,0x00,0x16,0x19,0x00,0x00,0x19,0x19,0x00,0x00,0x1C,0x19,0x00,0x00,
0x1F,0x19,0x00,0x00,0x22,0x19,0x00,0x00,0x28,0x19,0x00,0x00,0x25,0x19,0x00,0x00,
0x54,0x10,0x00,0x00,0x2B,0x19,0x00,0x00,0x50,0x3B,0x07,0x0C,0x51,0x3B,0xFD,0x0B,
0x60,0x95,0x65,0x93,0xCD,0x7B,0x81,0x07,0x21,0x33,0x61,0xA4,0x0F,0x32,0x63,0x98,
0x46,0xA3,0x67,0x83,0x40,0x3B,0x1C,0x0C,0x60,0x95,0x6E,0x93,0xCD,0x7B,0x63,0x98,
0x00,0x32,0x47,0xA3,0x01,0x30,0x00,0x33,0x68,0xA4,0x69,0xA4,0x00,0xE0,0x6B,0x05,
0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x02,0x30,0xCD,0x7B,0x68,0x48,0x04,0xA4,
0x65,0xA4,0x70,0x48,0x18,0x48,0x66,0xA4,0x07,0xA4,0x00,0xE0,0xA7,0x04,0x00,0x30,
0x00,0xE0,0x59,0x05,0x60,0x95,0x6F,0x93,0x05,0x32,0x0A,0x31,0x05,0x30,0xCD,0x7B,
0x40,0x38,0x0B,0x0C,0x04,0x33,0x0C,0x68,0x00,0x74,0x40,0x38,0x06,0x0C,0x00,0xE0,
0x44,0x06,0x63,0x98,0x01,0x32,0x47,0xA3,0x00,0x33,0x0E,0x1A,0x60,0xA2,0x45,0x84,
0x23,0x33,0x61,0xA4,0x48,0x42,0x64,0x84,0x8C,0x6C,0x66,0x84,0x70,0x43,0x8C,0x6C,
0x67,0x84,0x78,0x43,0xC8,0x6C,0x4A,0x98,0x20,0x92,0xC4,0x64,0x58,0x08,0x10,0x32,
0x8C,0x60,0x86,0x60,0x45,0x4A,0x28,0x98,0x49,0xA9,0x4A,0x98,0x60,0xB2,0x60,0x95,
0x70,0x93,0x0E,0x18,0xCD,0x7B,0xF0,0x33,0x5F,0x84,0xCA,0x64,0x67,0x98,0x68,0x83,
0x48,0x08,0xA3,0x3B,0x47,0x98,0x68,0xA2,0x6B,0x98,0x70,0x93,0x66,0xB8,0x69,0x98,
0x60,0x93,0x66,0x93,0x5F,0x6C,0x06,0x98,0xCD,0x7B,0xDF,0x38,0x02,0x0C,0x00,0x30,
0xC0,0x74,0x66,0xB8,0x4E,0xD8,0x18,0x00,0x63,0x98,0x45,0xA3,0x71,0x84,0x40,0x3B,
0x0F,0x08,0x60,0x95,0xFA,0x30,0x68,0x93,0x02,0x40,0xCD,0x7B,0x63,0x98,0x6D,0x83,
0x40,0x3B,0x06,0x08,0x64,0x98,0x60,0x93,0x6F,0x93,0x00,0x30,0xCD,0x7B,0x00,0x33,
0x63,0xA4,0xFF,0x32,0x7F,0x84,0x8E,0x64,0x1E,0x08,0x70,0x84,0x40,0x3B,0x0B,0x08,
0x0F,0x33,0x54,0x84,0x8C,0x68,0x60,0x95,0x72,0x93,0x8F,0x6D,0x26,0x98,0x01,0x33,
0x1F,0x6C,0xD9,0x7B,0x60,0x95,0x71,0x93,0x01,0x32,0x26,0x98,0x1F,0x6C,0xCD,0x7B,
0x20,0x04,0x00,0x00,0x00,0x80,0xFF,0xFF,0x00,0xA5,0xFF,0xFF,0x0F,0x32,0xA9,0x07,
0x83,0x3B,0xB9,0x07,0xF0,0x32,0x8E,0x64,0x14,0x08,0x6F,0x01,0x13,0x83,0x00,0x31,
0x01,0x29,0x02,0x74,0x42,0x64,0x6D,0xB8,0x2C,0xB8,0xE5,0x0F,0x63,0x98,0x01,0x32,
0x45,0xA3,0x40,0x95,0x00,0x74,0x53,0x92,0xC9,0x7B,0x2C,0x98,0x6D,0x98,0x33,0xA3,
0x7B,0x84,0x5A,0x84,0x68,0x43,0xC8,0x6C,0x40,0x3B,0x08,0x08,0x63,0x98,0x65,0x83,
0x40,0x3B,0x04,0x08,0x70,0x84,0x40,0x3B,0x56,0x0C,0x00,0x33,0x68,0xA4,0x69,0xA4,
0x24,0x33,0x61,0xA4,0x00,0x32,0x63,0x98,0x52,0xA3,0x64,0x98,0x40,0x93,0x80,0x36,
0x98,0x60,0x76,0x92,0xCD,0x7B,0x64,0x98,0x60,0x93,0xD8,0x60,0x77,0x93,0xCD,0x7B,
0x7E,0x84,0x4A,0x3B,0x11,0x0C,0x00,0x32,0x28,0x30,0x6A,0x02,0xC8,0x60,0x2A,0x02,
0xCA,0x02,0x4C,0x60,0xD8,0x60,0x20,0x89,0x60,0x8B,0x4E,0x60,0x3E,0x39,0x52,0x0D,
0x01,0x22,0x0A,0x64,0xF3,0x0B,0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x02,0x30,
0xCD,0x7B,0x68,0x48,0x59,0x84,0x65,0xA4,0x70,0x48,0x66,0xA4,0x48,0x42,0x78,0x84,
0x8C,0x6C,0x04,0xA4,0x40,0x3A,0x18,0x48,0x07,0xA4,0x46,0xB8,0x28,0x0C,0x60,0x95,
0x66,0x93,0x0A,0x30,0xCD,0x7B,0x64,0x98,0x60,0x93,0x65,0x93,0x01,0x32,0x21,0x31,
0x08,0x30,0xCD,0x7B,0x79,0x84,0x58,0x84,0x68,0x43,0xC8,0x6C,0x00,0x2B,0xCD,0x74,
0x78,0xA4,0x68,0x4B,0x79,0xA4,0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x01,0x30,
0xCD,0x7B,0x80,0x04,0x69,0x84,0x48,0x84,0x68,0x43,0xC8,0x6C,0x48,0x03,0xC8,0x64,
0xA8,0x0F,0x00,0x23,0xCD,0x74,0x68,0xA4,0x68,0x4B,0xA2,0x07,0x63,0x98,0x60,0x83,
0x40,0x3B,0x10,0x08,0x63,0x98,0x63,0x83,0x40,0x3B,0x0C,0x0C,0x63,0x98,0x00,0x32,
0x45,0xA3,0x00,0x33,0x68,0xA4,0x00,0x33,0x7F,0x2B,0x69,0xA4,0x00,0x33,0x78,0xA4,
0x79,0xA4,0x69,0x84,0x48,0x84,0x68,0x43,0xC8,0x6C,0x40,0x3B,0x05,0x08,0x60,0x95,
0x66,0x93,0x0A,0x30,0xCD,0x7B,0x63,0x98,0x60,0x83,0x40,0x3B,0xB4,0x08,0x69,0x84,
0x48,0x84,0x68,0x43,0xC8,0x6C,0xCF,0x74,0xDF,0x3B,0xAD,0x0C,0x60,0x95,0x66,0x93,
0xC8,0x30,0xCD,0x7B,0x60,0x95,0x6C,0x93,0x9F,0x6C,0x00,0x31,0x01,0x30,0xCD,0x7B,
0x63,0x98,0x60,0x83,0x40,0x3B,0x23,0x08,0x63,0x98,0x00,0x32,0x52,0xA3,0x60,0x95,
0x6C,0x93,0x9F,0x6C,0x28,0x31,0x00,0x30,0xCD,0x7B,0x63,0x98,0xC3,0x83,0x40,0x3E,
0x52,0x08,0x65,0x98,0x47,0x83,0x68,0x83,0x68,0x43,0xC8,0x6C,0x45,0x98,0x25,0x82,
0x46,0x82,0x48,0x42,0x84,0x6C,0xCA,0x60,0xCF,0x74,0xDF,0x3B,0x03,0x0C,0x00,0x32,
0x6D,0x5A,0x4F,0x32,0xC9,0x64,0x60,0x0C,0x43,0x3E,0x49,0x08,0x60,0x95,0x66,0x93,
0x0A,0x30,0xCD,0x7B,0x00,0x33,0x02,0x2B,0x68,0xA4,0x7F,0x33,0x69,0xA4,0x63,0x98,
0x61,0x83,0x00,0x2B,0xCC,0x74,0xFD,0x32,0xC8,0x64,0x03,0x0C,0x43,0x98,0x61,0xA2,
0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x01,0x30,0xCD,0x7B,0x63,0x98,0x00,0x32,
0x52,0xA3,0x26,0x33,0x61,0xA4,0x70,0x84,0x40,0x3B,0x7C,0x0C,0x01,0x33,0x71,0xA4,
0x69,0x98,0x60,0x93,0x7F,0x23,0x68,0x93,0x38,0x32,0x00,0x31,0x14,0x12,0xCD,0x7B,
0x60,0x95,0x0B,0x93,0xC1,0x7B,0x40,0x38,0x04,0x0C,0x60,0x95,0x6A,0x93,0xCD,0x7B,
0x60,0x95,0x07,0x93,0xC1,0x7B,0x40,0x38,0x6C,0x0C,0x00,0x32,0x63,0x98,0x00,0x2A,
0x4A,0xA3,0x67,0x04,0x60,0x95,0x07,0x93,0xC1,0x7B,0xC6,0x98,0x64,0x98,0x60,0x93,
0x68,0x93,0x00,0x31,0x01,0x30,0xCD,0x7B,0xC6,0xB8,0x93,0x07,0x60,0x95,0x6C,0x93,
0x9F,0x6C,0x28,0x31,0x00,0x30,0xCD,0x7B,0x65,0x98,0x47,0x83,0x68,0x83,0x68,0x43,
0xC8,0x6C,0x45,0x98,0x25,0x82,0x46,0x82,0x48,0x42,0x84,0x6C,0xCA,0x60,0x00,0x26,
0xCF,0x74,0x98,0x75,0x9B,0x07,0x43,0x3E,0xA2,0x0F,0x00,0xE0,0x55,0x02,0x64,0x98,
0x60,0x93,0x65,0x93,0x01,0x32,0x22,0x31,0x0A,0x30,0xCD,0x7B,0x75,0x11,0x09,0x32,
0x47,0xA3,0x61,0x83,0xA0,0x3B,0x53,0x11,0x61,0xA2,0x02,0x33,0x0C,0x68,0x00,0x74,
0x40,0x38,0x8D,0x0B,0x66,0x98,0xC2,0x5B,0x46,0x98,0xC7,0x33,0x8C,0x64,0x99,0x75,
0xC6,0x0B,0x85,0x07,0x69,0x84,0x48,0x84,0x68,0x43,0xC8,0x6C,0x4A,0x11,0xC8,0x64,
0x05,0x08,0x60,0x95,0x66,0x93,0x28,0x30,0xCD,0x7B,0x64,0x98,0x60,0x93,0x65,0x93,
0x01,0x32,0x21,0x31,0x0A,0x30,0xCD,0x7B,0x08,0x33,0x0C,0x68,0x00,0x74,0x40,0x38,
0x77,0x0B,0x64,0x98,0x60,0x93,0x65,0x93,0x01,0x32,0x21,0x31,0x08,0x30,0xCD,0x7B,
0x6F,0x07,0x00,0x33,0x71,0xA4,0x60,0x95,0x0B,0x93,0xC1,0x7B,0x40,0x38,0x13,0x08,
0x00,0xE0,0xA4,0x02,0x6B,0x84,0x4A,0x84,0x68,0x43,0xC8,0x6C,0xFE,0x32,0xC8,0x64,
0x03,0x08,0x00,0xE8,0x53,0xFD,0x00,0x23,0xCD,0x74,0x6A,0xA4,0x68,0x4B,0x6B,0xA4,
0x00,0xE8,0x4C,0xFD,0x60,0x95,0x6A,0x93,0xCD,0x7B,0x60,0x95,0x07,0x93,0xC1,0x7B,
0xE8,0x07,0x00,0x33,0x79,0x2B,0x68,0xA4,0x01,0x33,0x69,0xA4,0x60,0x95,0x66,0x93,
0x0A,0x30,0xCD,0x7B,0xD1,0x06,0x00,0x00,0x28,0x55,0x00,0x00,0xF4,0x3C,0x00,0x00,
0xE4,0x0E,0x00,0x00,0xBA,0x0E,0x00,0x00,0xFE,0x7F,0x00,0x00,0x9C,0x28,0x00,0x00,
0x00,0x20,0x00,0x40,0x8F,0x01,0x00,0x00,0xD4,0x14,0x24,0x14,0x88,0x12,0x41,0x84,
0x01,0x35,0x94,0x68,0x40,0x3A,0x0D,0x0C,0x47,0x84,0xFE,0x33,0x8C,0x68,0x47,0xA4,
0x64,0x12,0xCD,0x7B,0x67,0x84,0xD4,0x6C,0xCC,0x74,0x67,0xA4,0x04,0x14,0x94,0x14,
0x61,0x12,0x63,0xB8,0x53,0x6C,0x41,0x12,0x67,0x84,0xCE,0x74,0xDF,0x3B,0x04,0x08,
0x63,0x98,0x40,0x3B,0x4B,0x08,0x67,0x81,0x64,0x4B,0x07,0x32,0xC8,0x68,0x60,0xB8,
0xBB,0x11,0x00,0x33,0x66,0xA5,0x38,0x33,0x9A,0x11,0xD0,0x60,0x00,0x36,0x61,0xB8,
0x60,0x98,0x8E,0x65,0xE4,0x0F,0x52,0x11,0x67,0x82,0x0F,0x31,0xC4,0x68,0x24,0x46,
0xC4,0x6C,0xCC,0x74,0x67,0xA2,0xE3,0x82,0x46,0x85,0x01,0x3A,0xDC,0x75,0x2B,0x85,
0x4D,0x08,0x10,0x8C,0xDD,0x74,0x08,0x40,0x0C,0x6C,0x01,0x74,0x40,0x39,0x10,0xAC,
0x36,0x0C,0x40,0x3A,0x19,0x08,0x4D,0x94,0x53,0x92,0x1F,0x6C,0x62,0xB8,0xC9,0x7B,
0x40,0x38,0x62,0x98,0x08,0x0C,0x01,0x32,0x4A,0xA5,0x00,0x32,0x4B,0xA5,0x01,0x31,
0x4B,0x94,0x20,0xA2,0x53,0x85,0xCA,0x65,0x19,0x08,0x00,0x33,0x67,0xA5,0x00,0x33,
0x74,0xAC,0x65,0x94,0xCD,0x7B,0x66,0x85,0x41,0x3B,0x04,0x08,0x61,0x98,0x00,0x32,
0x54,0xA3,0x66,0x94,0x1F,0x6C,0xCD,0x7B,0x16,0x04,0xA0,0x33,0x62,0xAA,0x00,0x33,
0x62,0xAA,0x63,0x98,0x00,0x2B,0x63,0xB8,0xA8,0x07,0x54,0x8C,0x89,0x74,0x48,0x42,
0x89,0x74,0x54,0xAC,0x54,0x8C,0x89,0x74,0xC8,0x6C,0xE3,0x07,0x40,0x3A,0x09,0x08,
0x61,0x94,0xCD,0x7B,0x66,0x85,0x00,0x23,0x66,0xA5,0x00,0x26,0x98,0x75,0xA9,0x07,
0x62,0x94,0x08,0x48,0xCD,0x7B,0x62,0x94,0xDE,0x07,0x40,0x39,0x05,0x0C,0x66,0x94,
0x1F,0x6C,0xCD,0x7B,0xF3,0x07,0x62,0x94,0xFC,0x07,0x00,0x00,0x00,0x20,0x00,0x40,
0x68,0x1E,0x01,0x00,0x10,0x27,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x3C,0x00,0x00,
0xE0,0x3B,0x00,0x00,0xD4,0x14,0x27,0x14,0x61,0xB8,0x6E,0xD8,0x1A,0x10,0x51,0x3B,
0x87,0x6D,0x4B,0x6D,0xEE,0xD8,0x18,0x10,0x60,0xB8,0x31,0x08,0x68,0x4F,0x08,0x3B,
0x2E,0x0C,0x73,0x03,0x60,0x32,0x20,0x31,0x8C,0x60,0x4C,0x60,0x51,0x82,0x32,0x81,
0x7E,0x93,0x48,0x7C,0x4C,0x60,0x77,0x03,0x02,0x1C,0x60,0x93,0x7F,0x23,0x67,0x93,
0x13,0x6C,0xCD,0x7B,0x11,0x75,0x7A,0x03,0x83,0xAB,0x5B,0x03,0x62,0x8A,0xCD,0x74,
0xA4,0x3B,0x62,0xAA,0x6E,0xD8,0x02,0x10,0xCD,0x74,0x99,0x75,0x55,0x75,0xC4,0xAA,
0xA5,0xAA,0x66,0xAA,0x6E,0xD8,0x00,0x10,0xE1,0xAA,0x10,0x31,0x60,0xAA,0x62,0x8A,
0xCD,0x74,0xC4,0x68,0x40,0x3B,0xFC,0x0F,0x07,0x14,0x94,0x14,0x01,0x74,0x77,0x13,
0x03,0xAB,0xE4,0x07,0xD1,0x14,0x74,0x13,0x0A,0x32,0x60,0x93,0x83,0x93,0x03,0x31,
0x73,0x13,0xD1,0x7B,0x00,0x30,0x91,0x14,0xD4,0x14,0x23,0x14,0x83,0x6D,0x4B,0x6C,
0x40,0xB8,0x70,0x13,0x63,0x83,0x0F,0x32,0xC9,0x68,0x40,0x3B,0x55,0x0C,0x6E,0x13,
0x80,0x83,0x40,0x3C,0x51,0x0C,0x6B,0x13,0x77,0x83,0x62,0xB8,0xA3,0x5C,0xA1,0xB8,
0xDF,0x3D,0x46,0x08,0x69,0x13,0x0C,0x61,0x84,0x44,0x04,0x61,0x11,0x04,0x00,0x33,
0x1E,0x04,0x00,0x32,0x24,0x04,0x61,0x98,0xD5,0x64,0x32,0x08,0x61,0x98,0x00,0x2B,
0x61,0xB8,0x00,0x2D,0x0F,0x2C,0x00,0x33,0x00,0x2B,0xD6,0x64,0x31,0x0C,0x13,0x6C,
0x41,0x8C,0x8B,0x74,0x47,0x52,0x20,0x8C,0x47,0x74,0x27,0x51,0x20,0x3A,0xE8,0x0B,
0x75,0x86,0xCE,0x74,0x00,0x2B,0xC9,0x64,0x02,0x0C,0xCB,0x6C,0x20,0x39,0xE2,0x0B,
0x54,0x86,0x8A,0x74,0x00,0x2A,0x85,0x64,0x02,0x0C,0x87,0x6C,0x22,0x98,0x61,0x43,
0xE1,0x96,0xDC,0x60,0x60,0x8B,0xCF,0x74,0xC5,0x64,0xD6,0x0F,0x22,0x98,0x62,0x96,
0x41,0x42,0x8C,0x60,0x60,0x8A,0xCF,0x74,0xC5,0x64,0xD4,0x0B,0xCD,0x07,0x21,0x98,
0x24,0x41,0x60,0x98,0x4C,0x60,0x10,0x32,0x00,0xE0,0x06,0x03,0xC8,0x07,0x61,0x98,
0x00,0x23,0x45,0x12,0x60,0xA2,0x00,0x30,0x03,0x14,0x94,0x14,0x64,0x12,0x05,0x12,
0x25,0x12,0x49,0x80,0x8A,0x74,0xDF,0x3A,0x09,0x08,0x00,0x2B,0xA0,0x32,0xCD,0x74,
0x42,0xA9,0x40,0x3B,0x00,0x32,0x42,0xA9,0xF5,0x0B,0x3C,0x78,0xD4,0x14,0x26,0x14,
0xBE,0x11,0x83,0x6D,0x6D,0x95,0x07,0x6D,0x04,0x30,0x3E,0x93,0x64,0x93,0x41,0xB8,
0xCD,0x7B,0x6D,0x95,0x7F,0x23,0x63,0x93,0x08,0x30,0xCD,0x7B,0x78,0x11,0x01,0x32,
0x40,0xAB,0x74,0x11,0x61,0x32,0x48,0xA3,0x60,0x32,0x49,0xA3,0x75,0x11,0x01,0x32,
0x42,0xA3,0x0C,0x32,0x44,0xA3,0x30,0x32,0x43,0xA3,0x61,0x98,0x18,0x61,0x00,0x37,
0x60,0xB8,0x82,0xB8,0x7F,0x2F,0x62,0x98,0xDA,0x64,0x03,0x08,0x06,0x14,0x94,0x14,
0x60,0x86,0x6E,0xDC,0x17,0x00,0x6D,0x95,0x7F,0x23,0x05,0x18,0x64,0x93,0x02,0x32,
0x01,0x31,0x02,0x20,0xCD,0x7B,0x00,0x34,0x07,0x32,0x40,0x33,0x0C,0x6D,0x53,0x6C,
0x5C,0x6C,0x63,0xB8,0x44,0x74,0x63,0x11,0x44,0xB8,0x25,0xA3,0x2D,0x95,0x27,0x91,
0x14,0x30,0xC5,0x7B,0x7F,0x10,0x26,0x83,0x40,0x30,0x40,0x68,0x40,0x39,0x63,0x98,
0x44,0x98,0x03,0x08,0x0D,0x69,0x10,0x75,0x00,0x2A,0x40,0x3A,0x61,0x4B,0xE7,0x0B,
0x6D,0x95,0x7F,0x23,0x05,0x18,0x64,0x93,0x08,0x32,0x01,0x31,0x02,0x20,0xCD,0x7B,
0x61,0x98,0x40,0x3B,0x04,0x0C,0x00,0x24,0x60,0x98,0x80,0xAB,0x6D,0x95,0x68,0x93,
0x00,0x31,0x01,0x30,0xCD,0x7B,0x60,0x98,0x01,0x23,0x60,0xB8,0x00,0x26,0xBC,0x07,
0x18,0x3C,0x00,0x00,0xE4,0x54,0x00,0x00,0x00,0x11,0x00,0x40,0x68,0x10,0x00,0x00,
0xE8,0x54,0x00,0x00,0x30,0x55,0x00,0x00,0xFF,0xFF,0xFF,0x0F,0x20,0x4E,0x00,0x00,
0x00,0x03,0x00,0x40,0x00,0x02,0x00,0x40,0xE0,0x3B,0x00,0x00,0x00,0x10,0x00,0x40,
0x60,0x12,0x00,0x40,0xC1,0x14,0x21,0x14,0x72,0x00,0x31,0x00,0x60,0xB8,0x11,0x00,
0xC7,0x6C,0x44,0x81,0x08,0x34,0x90,0x68,0x40,0x3A,0x04,0x0C,0x40,0x98,0x40,0x3A,
0x0B,0x08,0x41,0x83,0xFE,0x31,0x84,0x68,0x41,0xA3,0x00,0x32,0x46,0xA3,0x0B,0x32,
0x47,0xA3,0x01,0x14,0x81,0x14,0xA0,0x32,0x42,0xA8,0x00,0x32,0x42,0xA8,0x40,0x98,
0x00,0x2A,0x40,0xB8,0xE7,0x07,0xD4,0x14,0x21,0x14,0x7F,0x00,0xB8,0x35,0x4C,0x61,
0x21,0x95,0xC0,0x01,0x82,0x8E,0x6D,0x93,0x20,0xB8,0x02,0x31,0x22,0xAE,0x3E,0x93,
0x7F,0x23,0x83,0x6C,0x21,0xB5,0xEB,0x93,0x01,0x31,0x01,0x33,0x01,0x30,0x11,0x75,
0xDD,0x7B,0x10,0x75,0x60,0x98,0x82,0xAE,0x61,0xB5,0x01,0x14,0x94,0x14,0xD4,0x14,
0x22,0x14,0x8D,0x01,0x80,0x35,0x61,0xB8,0x6D,0x94,0xC3,0x6D,0xD4,0x60,0x40,0xB8,
0xD4,0x93,0x08,0x32,0x00,0x33,0x07,0x6C,0x5F,0x6C,0xD9,0x7B,0x83,0x6D,0xFF,0xE3,
0x1F,0xFF,0x01,0x30,0xFF,0xE3,0xD1,0xFF,0x6D,0x94,0xD4,0x60,0x01,0x30,0x75,0x93,
0xCD,0x7B,0x6D,0x94,0x4C,0x61,0x77,0x95,0xCD,0x7B,0x79,0x01,0x60,0x93,0x19,0x01,
0xA3,0x93,0x10,0x60,0x60,0x98,0x41,0x98,0x5B,0x6C,0xD5,0x7B,0x02,0x14,0x94,0x14,
0x00,0x74,0x7D,0x01,0x01,0xA3,0x01,0x31,0x43,0x83,0x84,0x68,0x40,0x3A,0xFD,0x0F,
0x01,0x32,0x00,0x30,0x43,0xA3,0x3C,0x78,0xD3,0x14,0x00,0x33,0x83,0x02,0x7F,0x2B,
0x68,0xA4,0x00,0x33,0x69,0xA4,0x47,0x6D,0x6B,0x02,0x83,0x6D,0x6D,0x93,0x0A,0x30,
0x66,0x93,0xCD,0x7B,0xC8,0xA4,0x00,0x30,0xA9,0xA4,0x50,0x02,0x2A,0x02,0x69,0x84,
0xCE,0x74,0xDF,0x3B,0x09,0x08,0x00,0x20,0xA0,0x33,0x01,0x74,0x62,0xAA,0x42,0x64,
0x00,0x33,0x62,0xAA,0xF5,0x0B,0x93,0x14,0xD4,0x14,0x21,0x14,0x8A,0x30,0x98,0x02,
0x01,0x40,0x10,0x60,0x60,0x80,0x60,0xB8,0x8F,0x6C,0xF2,0x33,0xF5,0x02,0x64,0x43,
0x4C,0x31,0xA1,0x80,0x40,0x60,0x80,0x36,0x0C,0x60,0x60,0x97,0x94,0x7C,0xD8,0x60,
0x41,0x42,0x67,0x93,0xCD,0x7B,0x60,0x97,0xD8,0x60,0x3B,0x02,0x1B,0x02,0x41,0x45,
0x50,0x60,0x10,0x60,0x67,0x93,0xCD,0x7B,0x60,0x98,0x41,0x43,0x60,0x97,0x8C,0x61,
0x3F,0x02,0x1E,0x02,0x50,0x60,0x10,0x60,0x67,0x96,0xCD,0x7B,0x01,0x14,0x94,0x14,
0xD4,0x14,0x3E,0x15,0x04,0xB8,0x0E,0x32,0x87,0x6D,0x05,0x18,0x24,0x03,0x00,0xE0,
0xA3,0x01,0x22,0x32,0x00,0x31,0x09,0x18,0x00,0xE0,0xA8,0x01,0x00,0x33,0x05,0x1A,
0x8C,0x60,0x40,0x82,0x09,0x19,0x00,0x23,0x84,0x60,0x4E,0x3B,0x01,0x31,0x20,0xA2,
0xF7,0x0B,0x2C,0x03,0x84,0x91,0xA2,0x91,0x00,0x32,0x00,0x33,0x23,0xB8,0x09,0x19,
0x48,0x60,0x20,0x81,0x04,0x98,0x06,0x64,0x17,0x08,0x28,0x5C,0x24,0x18,0x20,0x81,
0x0C,0x60,0x20,0xA0,0x28,0x5D,0x1B,0x18,0x0C,0x60,0x20,0x81,0x40,0x3E,0x20,0xA0,
0x09,0x08,0x17,0x03,0x23,0x98,0x08,0x60,0x04,0x60,0x12,0x19,0x4C,0x60,0x00,0x80,
0x00,0xA1,0x00,0x23,0xCC,0x74,0x00,0x22,0x22,0x31,0x4A,0x64,0xE1,0x0B,0x40,0x3B,
0x47,0x0C,0xB2,0x13,0x80,0x34,0x4D,0x95,0x61,0xB8,0x12,0x1B,0x90,0x60,0xC2,0xB8,
0x60,0xB8,0x6D,0x92,0xCF,0x6D,0x1B,0x1A,0x2D,0x1B,0x24,0x19,0x1A,0x13,0xDD,0x7B,
0x7A,0x13,0x26,0x83,0x6D,0x95,0xD0,0x60,0x00,0x32,0x6E,0x93,0x30,0x30,0xCD,0x7B,
0xFF,0xE3,0x56,0xFE,0x00,0x30,0xFF,0xE3,0x08,0xFF,0x6D,0x95,0xD0,0x60,0x6F,0x93,
0xCD,0x7B,0x6D,0x95,0x0C,0x61,0x71,0x94,0xCD,0x7B,0x00,0x33,0x00,0x32,0x22,0x30,
0x09,0x19,0x4C,0x60,0x20,0x81,0x84,0x98,0x06,0x65,0x17,0x08,0x8C,0x13,0x21,0x43,
0x50,0x60,0x83,0x98,0x50,0x60,0x2D,0x1D,0x81,0x42,0x14,0x61,0x80,0x8C,0x40,0x3E,
0x80,0xA9,0x09,0x0C,0x23,0x13,0x83,0x98,0x4C,0x60,0x50,0x60,0x12,0x1C,0x08,0x61,
0x80,0x84,0x80,0xA1,0x00,0x22,0x88,0x74,0x00,0x23,0x0E,0x64,0xE2,0x0B,0x1E,0x15,
0x94,0x14,0xD4,0x14,0x25,0x14,0x8A,0x35,0x8C,0x12,0xA1,0x45,0x7D,0x12,0x40,0x38,
0xC3,0x6D,0x50,0x61,0x64,0xB8,0x80,0x0C,0x6D,0x94,0x7F,0x23,0x79,0x93,0xCD,0x7B,
0xE2,0xB8,0x40,0x85,0x41,0xB8,0x58,0x12,0x6D,0x94,0x94,0x60,0x40,0xB8,0x7F,0x23,
0x6D,0x93,0x8F,0x6D,0x41,0x95,0x75,0x12,0x23,0x95,0x0F,0x12,0xD9,0x7B,0x71,0x12,
0x1F,0x23,0x26,0x83,0x6D,0x94,0x7F,0x23,0x00,0x32,0x6E,0x93,0x30,0x30,0xCD,0x7B,
0xFF,0xE3,0xFE,0xFD,0x00,0x30,0xFF,0xE3,0xB0,0xFE,0x6D,0x94,0x7F,0x23,0x6F,0x93,
0xCD,0x7B,0x6D,0x94,0x7F,0x23,0x71,0x93,0xCD,0x7B,0x5F,0x6C,0x00,0x30,0xFF,0xE3,
0x41,0xFF,0x5F,0x6C,0x01,0x30,0xFF,0xE3,0x3D,0xFF,0x40,0x3F,0x15,0x0C,0x60,0x85,
0x63,0xB8,0x00,0x31,0x00,0x32,0x3F,0x36,0xC4,0x74,0x03,0x98,0x0C,0x64,0xA1,0x0C,
0xFF,0x31,0x85,0x64,0xCB,0x6C,0x02,0x0C,0xFF,0x33,0x8F,0x74,0xDF,0x3A,0x02,0x0C,
0x00,0x33,0x5B,0x11,0x61,0xA2,0x80,0x36,0x6D,0x94,0x3A,0x11,0x20,0xB8,0x97,0x6C,
0xD8,0x60,0xE1,0xB8,0xB2,0x93,0x4B,0x22,0x77,0x11,0x2D,0x11,0x17,0x11,0xD5,0x7B,
0x57,0x11,0x60,0x33,0xC8,0x60,0x0A,0x31,0x31,0xA3,0x03,0x31,0x30,0xA3,0x75,0x11,
0x7D,0xB2,0x63,0x23,0x7E,0xB2,0x64,0x98,0x1F,0x23,0x26,0x83,0x6D,0x94,0xD8,0x60,
0x08,0x32,0xB4,0x93,0x30,0x30,0x00,0x33,0xD5,0x7B,0xFF,0xE3,0xB1,0xFD,0x01,0x30,
0xFF,0xE3,0x63,0xFE,0x6D,0x94,0xD8,0x60,0x75,0x93,0x00,0x30,0xCD,0x7B,0x40,0x3F,
0x09,0x0C,0x6D,0x94,0xD8,0x60,0x76,0x93,0xCD,0x7B,0x6D,0x94,0x8C,0x61,0x77,0x96,
0xCD,0x7B,0x05,0x14,0x94,0x14,0x3B,0x10,0x6D,0x94,0x77,0x21,0x01,0xB8,0x20,0xB8,
0x7F,0x23,0x72,0x93,0x8F,0x6D,0x4C,0x32,0x3E,0x04,0x00,0x00,0x10,0x27,0x00,0x00,
0x00,0x20,0x00,0x40,0x00,0x02,0x00,0x40,0xE0,0x3B,0x00,0x00,0x00,0x10,0x00,0x40,
0xD0,0x51,0x00,0x00,0x34,0x10,0x00,0x00,0x20,0x20,0x00,0x40,0x00,0x03,0x00,0x40,
0x50,0xC3,0x00,0x00,0xE4,0x54,0x00,0x00,0x22,0x0F,0x00,0x00,0x84,0x15,0x00,0x00,
0xCE,0x0F,0x00,0x00,0xC8,0x15,0x00,0x00,0x28,0x18,0x00,0x00,0xF4,0x3C,0x00,0x00,
0x98,0x0E,0x00,0x00,0xE4,0x01,0x00,0x00,0xF4,0x51,0x00,0x00,0x0E,0x0E,0x00,0x00,
0xD4,0x51,0x00,0x00,0x0C,0x0F,0x00,0x00,0xAE,0x4B,0x00,0x00,0x7C,0x54,0x00,0x00,
0x4C,0x52,0x00,0x00,0xE2,0x47,0x00,0x00,0xD4,0x01,0x00,0x00,0x18,0x3C,0x00,0x00,
0x36,0x18,0x00,0x00,0x62,0x11,0x94,0x60,0xD0,0x60,0x57,0x6C,0x01,0x11,0xD9,0x7B,
0x6D,0x94,0x7F,0x23,0x8F,0x6D,0x90,0x33,0x61,0xB8,0xE0,0xB8,0x00,0x33,0xDA,0x96,
0x32,0x32,0x20,0x31,0x0F,0x30,0xD9,0x7B,0x7B,0x10,0x1F,0x23,0x06,0xA3,0x29,0x07,
0x7A,0x10,0xC4,0x60,0xD4,0x60,0x60,0x83,0x0E,0x74,0xDF,0x38,0x08,0x0C,0x40,0x30,
0x0C,0x68,0x40,0x38,0xD8,0x68,0x05,0x0C,0x8E,0x60,0x8B,0x74,0x00,0x21,0x4D,0x07,
0xC8,0x60,0x8F,0x74,0xFC,0x07,0xD3,0x14,0xB1,0x10,0x80,0x34,0x60,0x95,0xD1,0x10,
0xD0,0x60,0xAA,0x32,0x68,0x93,0x43,0x42,0x00,0x31,0x14,0x96,0xCD,0x7B,0x60,0x95,
0xD0,0x60,0x68,0x93,0x44,0x32,0x00,0x31,0x15,0x96,0xCD,0x7B,0x60,0x95,0xD0,0x60,
0x16,0x96,0x68,0x93,0x28,0x32,0x00,0x31,0xCD,0x7B,0x93,0x14,0x02,0x0C,0x00,0x00,
0xD4,0x01,0x00,0x00,0xD4,0x51,0x00,0x00,0x0C,0x0F,0x00,0x00,0xE4,0x54,0x00,0x00,
0x88,0x54,0x00,0x00,0xD0,0x14,0x64,0x10,0x60,0x93,0x7F,0x23,0x67,0x93,0xCD,0x7B,
0x90,0x14,0x00,0x00,0xE4,0x54,0x00,0x00,0xD0,0x14,0x64,0x10,0x60,0x93,0x7F,0x23,
0x68,0x93,0xCD,0x7B,0x90,0x14,0x00,0x00,0xE4,0x54,0x00,0x00,0x00,0x00,0x00,0x00,
0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x00,0x41,0x25,0x0D,0x70,0x73,0x67,0x1E,0x00,
0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x30,0x00,0x46,0x73,0x67,0x04,0x0F,0x70,0x14,
0xFF,0x25,0x26,0x27,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x30,0x31,0xFF,0x32,
0x33,0x34,0x35,0x36,0x37,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x60,0x61,0x62,
0x63,0x64,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
0x20,0x21,0x22,0x23,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0x05,0x98,0x08,0xDA,0x0B,0xA1,0x0F,
0xED,0x13,0xB8,0x18,0xFD,0x1D,0xAF,0x23,0xC1,0x29,0x22,0x30,0xBE,0x36,0x7D,0x3D,
0x48,0x44,0x04,0x4B,0x95,0x51,0xE1,0x57,0xCD,0x5D,0x3D,0x63,0x19,0x68,0x4C,0x6C,
0xC0,0x6F,0x66,0x72,0x32,0x74,0x1A,0x75,0x1A,0x75,0x32,0x74,0x66,0x72,0xC0,0x6F,
0x4C,0x6C,0x19,0x68,0x3D,0x63,0xCD,0x5D,0xE1,0x57,0x95,0x51,0x04,0x4B,0x48,0x44,
0x7D,0x3D,0xBE,0x36,0x22,0x30,0xC1,0x29,0xAF,0x23,0xFD,0x1D,0xB8,0x18,0xED,0x13,
0xA1,0x0F,0xDA,0x0B,0x98,0x08,0xD9,0x05,0x00,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
0x10,0x1D,0x1E,0x1F,0x20,0x21,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,
0x01,0x00,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x00,0x01,0xFF,0x01,
0xFF,0x01,0xFF,0x01,0x01,0x01,0x01,0x00,0xFF,0xFF,0x01,0x01,0x01,0xFF,0x01,0x01,
0xFF,0xFF,0x00,0x01,0x01,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0x00,0x01,0x01,
0xFF,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0x00,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,
0xFF,0x01,0x01,0x00,0x01,0x01,0xFF,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0x00,0x01,
0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x01,
0x01,0x81,0x81,0x81,0x01,0x00,0x01,0x01,0x01,0x81,0x81,0x81,0x01,0x01,0x01,0x01,
0x00,0x01,0x81,0x01,0x81,0x01,0x81,0x01,0x01,0x01,0x01,0x00,0x81,0x81,0x01,0x01,
0x01,0x81,0x01,0x01,0x81,0x81,0x00,0x01,0x01,0x81,0x01,0x01,0x01,0x81,0x01,0x81,
0x01,0x00,0x01,0x01,0x81,0x01,0x01,0x81,0x81,0x01,0x01,0x01,0x00,0x01,0x01,0x81,
0x81,0x81,0x01,0x01,0x81,0x01,0x01,0x00,0x01,0x01,0x81,0x01,0x81,0x01,0x01,0x81,
0x01,0x01,0x00,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x00,0x42,0x30,
0x00,0x43,0x31,0x00,0x4D,0x30,0x00,0x46,0x32,0x00,0x47,0x32,0x00,0x6F,0x31,0x00,
0x6F,0x32,0x00,0x70,0x30,0x00,0x70,0x38,0x00,0x70,0x32,0x00,0x70,0x36,0x00,0x71,
0x31,0x00,0x71,0x32,0x00,0x72,0x31,0x00,0x72,0x32,0x00,0x71,0x30,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,0x48,0xBE,0xA8,
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,984 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst7xx_fw.h
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef HYNITRON_FIRMWARE_H
#define HYNITRON_FIRMWARE_H
static const uint8_t fw_bin[] = {
0x00, 0x00, 0x00, 0x3c, 0x0b, 0x04,
0x02, 0x05, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x35, 0xee, 0x41, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02,
0x34, 0xaf, 0xee, 0x30, 0xe7, 0x07, 0xc3, 0xe4, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x22, 0x00, 0x00,
0x00, 0x02, 0x0a, 0xe2, 0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08,
0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32,
0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70,
0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83,
0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08,
0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2,
0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2,
0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82,
0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf,
0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9,
0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8,
0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83,
0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08,
0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed,
0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50,
0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x00, 0x74, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a,
0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83,
0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83,
0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82,
0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22,
0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01,
0xf3, 0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0,
0xa4, 0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad,
0xf0, 0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33,
0xfc, 0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4,
0xce, 0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75,
0xf0, 0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2,
0x22, 0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xc2, 0xd5, 0xec, 0x30, 0xe7, 0x09, 0xb2,
0xd5, 0xe4, 0xc3, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0xee, 0x30, 0xe7, 0x15, 0xb2, 0xd5, 0xe4, 0xc3,
0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x12, 0x01, 0x84, 0xc3, 0xe4, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0x80,
0x03, 0x12, 0x01, 0x84, 0x30, 0xd5, 0x07, 0xc3, 0xe4, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x22, 0xc5,
0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15,
0x83, 0xe0, 0x38, 0xf0, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xf5, 0xf0, 0xa3,
0xe0, 0x22, 0x50, 0x06, 0x87, 0xf0, 0x09, 0xe7, 0x19, 0x22, 0xbb, 0xfe, 0x07, 0xe3, 0xf5, 0xf0,
0x09, 0xe3, 0x19, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xf5, 0xf0, 0x74, 0x01, 0x93, 0x22,
0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0,
0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe,
0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83,
0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0,
0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06,
0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82,
0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25,
0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5,
0xf0, 0x08, 0xf2, 0x22, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xed, 0x39, 0xfd, 0xec, 0x38, 0xfc,
0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, 0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c,
0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, 0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0,
0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, 0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc,
0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, 0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd,
0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, 0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22,
0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc,
0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40,
0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6,
0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9,
0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb,
0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb,
0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9,
0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc,
0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a,
0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f,
0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07,
0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8,
0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xef, 0x4b,
0xff, 0xee, 0x4a, 0xfe, 0xed, 0x49, 0xfd, 0xec, 0x48, 0xfc, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea,
0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xec, 0x64, 0x80, 0xc8, 0x64, 0x80, 0x98, 0x45, 0xf0,
0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45,
0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef,
0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, 0xee, 0x33, 0xfe, 0xed,
0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x08, 0xe6, 0xfe,
0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8,
0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0x22, 0xd0, 0x83, 0xd0,
0x82, 0xe4, 0x93, 0xf6, 0x08, 0x74, 0x01, 0x93, 0xf6, 0x08, 0x74, 0x02, 0x93, 0xf6, 0x08, 0x74,
0x03, 0x93, 0xf6, 0x74, 0x04, 0x73, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5,
0x83, 0x22, 0xfa, 0xe6, 0xfb, 0x08, 0x08, 0xe6, 0xf9, 0x25, 0xf0, 0xf6, 0x18, 0xe6, 0xca, 0x3a,
0xf6, 0x22, 0xec, 0x8e, 0xf0, 0xa4, 0xcc, 0xc5, 0xf0, 0xcc, 0xcd, 0xf8, 0xef, 0xa4, 0xce, 0xc5,
0xf0, 0x2d, 0xfd, 0xe4, 0x3c, 0xfc, 0xe8, 0xa4, 0x2e, 0xc8, 0xc5, 0xf0, 0x3d, 0xfd, 0xe4, 0x3c,
0xfc, 0xef, 0xa4, 0xff, 0xe5, 0xf0, 0x28, 0xfe, 0xe4, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0xef,
0x4e, 0x60, 0x12, 0xef, 0x60, 0x01, 0x0e, 0xed, 0xbb, 0x01, 0x0b, 0x89, 0x82, 0x8a, 0x83, 0xf0,
0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x22, 0x89, 0xf0, 0x50, 0x07, 0xf7, 0x09, 0xdf, 0xfc, 0xa9, 0xf0,
0x22, 0xbb, 0xfe, 0xfc, 0xf3, 0x09, 0xdf, 0xfc, 0xa9, 0xf0, 0x22, 0x78, 0xff, 0xe4, 0xf6, 0xd8,
0xfd, 0x90, 0x00, 0x00, 0x7f, 0x00, 0x7e, 0x06, 0xe4, 0xf0, 0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x75,
0x81, 0x9a, 0x75, 0xa0, 0x00, 0x02, 0x05, 0x63, 0x02, 0x2f, 0xf7, 0xe4, 0x93, 0xa3, 0xf8, 0xe4,
0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3,
0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40,
0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x90, 0x00, 0x09, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f,
0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25,
0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3,
0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5,
0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xc2, 0xd5, 0xe8, 0x30, 0xe7, 0x0f, 0xb2, 0xd5,
0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, 0xe4, 0x99, 0xf9, 0xe4, 0x98, 0xf8, 0xec, 0x30, 0xe7,
0x17, 0xb2, 0xd5, 0x12, 0x05, 0xde, 0x12, 0x03, 0x6c, 0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa,
0xe4, 0x99, 0xf9, 0xe4, 0x98, 0xf8, 0x80, 0x03, 0x12, 0x03, 0x6c, 0x30, 0xd5, 0x0d, 0xe4, 0xc3,
0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0xe4, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0x22, 0x00, 0x21, 0x22, 0x20,
0x23, 0x30, 0x34, 0x33, 0x32, 0x32, 0x31, 0x54, 0x46, 0x65, 0x34, 0x32, 0x32, 0x33, 0x46, 0x33,
0x30, 0x32, 0x30, 0x24, 0x01, 0x00, 0x01, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x01,
0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x76,
0xa7, 0x18, 0xa1, 0x23, 0x63, 0x45, 0x07, 0x65, 0xaa, 0x56, 0xa1, 0x78, 0x00, 0x21, 0x00, 0x00,
0x00, 0x00, 0xaa, 0x21, 0xaa, 0x43, 0xaa, 0x56, 0xa7, 0x81, 0x00, 0x21, 0xaa, 0x67, 0xaa, 0x23,
0xaa, 0x87, 0xaa, 0x32, 0xaa, 0x87, 0xaa, 0x32, 0xaa, 0x87, 0xaa, 0x32, 0xa1, 0x87, 0x06, 0x71,
0xaa, 0x87, 0xaa, 0x23, 0xaa, 0x87, 0xaa, 0x32, 0x00, 0x00, 0xaa, 0x87, 0xaa, 0x23, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xaa, 0x65, 0xaa, 0x87, 0xa6, 0x51, 0x06, 0x47, 0x00, 0x45, 0xa1, 0x28,
0xaa, 0x76, 0xa8, 0x12, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x34, 0xaa, 0x56, 0xa1, 0x78, 0x00, 0x21,
0x00, 0x00, 0xaa, 0x67, 0xaa, 0x23, 0xaa, 0xa1, 0xaa, 0x87, 0xaa, 0x32, 0xaa, 0x67, 0xaa, 0x23,
0xaa, 0x87, 0xaa, 0x32, 0xaa, 0xa1, 0xaa, 0x21, 0xaa, 0x56, 0xa7, 0x81, 0xaa, 0x21, 0x00, 0x00,
0xaa, 0x34, 0xaa, 0x65, 0xaa, 0x87, 0x46, 0x51, 0x03, 0x47, 0xaa, 0xa8, 0xaa, 0x21, 0xaa, 0x43,
0xaa, 0x56, 0xa7, 0x81, 0xaa, 0x34, 0xa5, 0x76, 0xa7, 0x18, 0xa1, 0x23, 0xa3, 0x45, 0xa4, 0x23,
0xa8, 0x21, 0xa6, 0x87, 0xa4, 0x32, 0x21, 0x78, 0xa5, 0x76, 0xa1, 0x23, 0x63, 0x45, 0x07, 0x65,
0x00, 0x00, 0x01, 0xe0, 0x01, 0xe0, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0,
0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0,
0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5,
0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5,
0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x11, 0x16, 0x24, 0x50, 0x01, 0xb1, 0x46, 0x45, 0x44, 0x43,
0x42, 0x41, 0x40, 0x67, 0x66, 0x64, 0x63, 0x62, 0x61, 0x60, 0x84, 0x83, 0x72, 0x71, 0x70, 0x57,
0x56, 0x55, 0x54, 0x53, 0x73, 0x74, 0x75, 0x76, 0x77, 0x80, 0x81, 0x82, 0x40, 0x47, 0x51, 0x50,
0x00, 0x00, 0x00, 0x00, 0x80, 0x28, 0x10, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x21, 0x23, 0x28,
0x02, 0xbc, 0x22, 0x23, 0x28, 0x02, 0xbc, 0x23, 0x22, 0x28, 0x02, 0xbc, 0x00, 0x00, 0x85, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x03, 0xc0, 0x03, 0xe8, 0x03, 0x84, 0x03, 0x84,
0x19, 0x03, 0x7b, 0x04, 0x04, 0x08, 0x08, 0x0c, 0xac, 0x11, 0x50, 0x15, 0xf4, 0x1a, 0x98, 0x1f,
0x3c, 0x25, 0x09, 0x26, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04,
0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x32, 0x04, 0x12, 0x0f, 0x1c, 0xe5, 0x32, 0xb4, 0x01, 0x03,
0x12, 0x0e, 0x7f, 0x12, 0x08, 0x18, 0xd5, 0x32, 0xef, 0x12, 0x0f, 0x1c, 0x78, 0x87, 0x7c, 0x02,
0x11, 0x70, 0x78, 0xb5, 0x7c, 0x01, 0x11, 0x70, 0x78, 0xdb, 0x7c, 0x02, 0x11, 0x70, 0x7f, 0x2a,
0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x5a, 0xf1, 0x36, 0xe4, 0x90, 0x04, 0x53, 0xf0, 0xa3, 0x04, 0xf0,
0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x04, 0xf0, 0x75, 0x1c, 0x09, 0x90, 0xff, 0x4a, 0x74, 0x09, 0xf0,
0x90, 0xff, 0x50, 0x74, 0x0f, 0xd1, 0xfa, 0x90, 0xff, 0x40, 0x74, 0x18, 0x91, 0xfe, 0x78, 0x8e,
0xe6, 0x90, 0xff, 0x42, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x10, 0xf0, 0x11, 0x7f, 0xf1, 0x08, 0x43,
0xad, 0x04, 0x11, 0x69, 0x90, 0xff, 0x43, 0xe0, 0x30, 0xe4, 0xf9, 0x91, 0xff, 0x78, 0x8d, 0xe6,
0x90, 0xff, 0x48, 0xf0, 0x11, 0x7f, 0x53, 0xad, 0xfb, 0x90, 0xff, 0x40, 0x74, 0x19, 0xf0, 0x22,
0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x01, 0x79, 0x61, 0x7e, 0x00, 0x7f, 0x54, 0x02, 0x00, 0xf4, 0x7b,
0x03, 0xc2, 0xaf, 0xd1, 0xe3, 0x71, 0xc9, 0x7d, 0x06, 0x11, 0xb7, 0xd2, 0xaf, 0x78, 0x8f, 0xe6,
0xfd, 0xeb, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x55, 0xb1, 0x66, 0xed, 0xf0, 0xd1, 0xe3, 0xe0, 0x24,
0x37, 0xd1, 0xdb, 0xe0, 0xfd, 0xeb, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x54, 0xb1, 0x66, 0xed, 0xf0,
0xaf, 0x03, 0x1b, 0xef, 0x70, 0xcb, 0x22, 0xef, 0x54, 0x07, 0x90, 0x07, 0xdd, 0x93, 0xfe, 0xf4,
0xfc, 0xef, 0x54, 0xf0, 0xff, 0x75, 0xa0, 0xff, 0x64, 0x10, 0x70, 0x11, 0x78, 0x12, 0xed, 0x30,
0xe2, 0x05, 0xe2, 0x4e, 0xf2, 0x80, 0x03, 0xe2, 0x5c, 0xf2, 0x18, 0x80, 0x0d, 0xef, 0x13, 0x13,
0x54, 0x3f, 0x24, 0x11, 0xf8, 0xbd, 0x02, 0x02, 0xe4, 0xfd, 0xed, 0x30, 0xe1, 0x05, 0xe2, 0x4e,
0xf2, 0x80, 0x03, 0xe2, 0x5c, 0xf2, 0x18, 0xed, 0x30, 0xe0, 0x05, 0xe2, 0x4e, 0xf2, 0x80, 0x03,
0xe2, 0x5c, 0xf2, 0xe4, 0xf5, 0xa0, 0x22, 0x78, 0x23, 0x7c, 0x00, 0x7a, 0x07, 0x79, 0xb5, 0x7f,
0x28, 0x12, 0x3a, 0x25, 0xe4, 0xf5, 0x4b, 0x90, 0x03, 0xc6, 0xe0, 0xff, 0x90, 0x03, 0xc5, 0xe0,
0xfe, 0x6f, 0xfd, 0x90, 0x03, 0xc7, 0xe0, 0x6d, 0xfb, 0xee, 0xb4, 0xac, 0x08, 0xa3, 0xe0, 0xb5,
0x03, 0x03, 0x75, 0x4b, 0x01, 0xe5, 0x4b, 0x60, 0x02, 0x80, 0x02, 0x7f, 0x40, 0x90, 0xff, 0x42,
0xef, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x40, 0x91, 0xfe, 0xe4, 0x90, 0xff, 0x4a, 0xf0, 0x90, 0xff,
0x50, 0x74, 0x0f, 0xf0, 0x43, 0xad, 0x04, 0x7f, 0x24, 0x7a, 0x00, 0x79, 0x23, 0x12, 0x39, 0x8b,
0x7f, 0x48, 0x7a, 0x00, 0x79, 0xdf, 0x12, 0x34, 0xa6, 0xe4, 0xfb, 0xe4, 0xfa, 0xe4, 0x90, 0xff,
0x54, 0xf0, 0x90, 0xff, 0x55, 0x74, 0xfa, 0xf0, 0x91, 0xf2, 0xb1, 0x30, 0xc3, 0x94, 0xe0, 0xec,
0x94, 0x1f, 0x40, 0x44, 0x90, 0xff, 0x50, 0xe0, 0x30, 0xe7, 0x06, 0xae, 0x07, 0x1f, 0xee, 0x70,
0xf3, 0x74, 0x23, 0x2a, 0xf8, 0xe6, 0x90, 0xff, 0x54, 0xf0, 0xe5, 0x4b, 0x60, 0x07, 0x90, 0x03,
0xc7, 0xe0, 0xff, 0x80, 0x02, 0x7f, 0x40, 0x90, 0xff, 0x55, 0xef, 0xf0, 0xc2, 0xaf, 0xb1, 0x70,
0x2a, 0x71, 0xd9, 0x7d, 0x06, 0xb1, 0x1e, 0xb1, 0x70, 0x2a, 0x71, 0xd9, 0x7d, 0x02, 0xd1, 0xee,
0x91, 0xf2, 0x91, 0xea, 0xe4, 0x78, 0x99, 0xf6, 0x0a, 0xea, 0xc3, 0x94, 0x24, 0x40, 0x9e, 0xe4,
0xff, 0xfa, 0x74, 0x23, 0x2a, 0xf8, 0xe6, 0x30, 0xe7, 0x02, 0x7b, 0x01, 0x06, 0x91, 0xf3, 0xb1,
0x30, 0xc3, 0x94, 0xe0, 0xec, 0x94, 0x1f, 0x50, 0x06, 0x74, 0x23, 0x2a, 0xf8, 0x16, 0x0f, 0x0a,
0xba, 0x24, 0xdf, 0xef, 0x6a, 0x60, 0x05, 0xeb, 0x70, 0x02, 0x21, 0x6b, 0x7a, 0x23, 0x74, 0x23,
0x2a, 0xf8, 0xe6, 0xff, 0x7e, 0x00, 0x7c, 0x00, 0x7d, 0xff, 0x12, 0x01, 0x72, 0x91, 0xf3, 0xf5,
0x83, 0x12, 0x3a, 0x2e, 0x91, 0xf3, 0x12, 0x17, 0x6c, 0xff, 0xea, 0x25, 0xe0, 0x24, 0xe7, 0xf5,
0x82, 0xe4, 0x34, 0x00, 0x91, 0xea, 0xaf, 0x02, 0x1a, 0xef, 0x70, 0xd2, 0x90, 0xff, 0x41, 0x04,
0xf0, 0x90, 0xff, 0x42, 0xf0, 0xe4, 0x90, 0xff, 0x87, 0xf0, 0x90, 0xff, 0x18, 0xf0, 0xfd, 0x7f,
0x10, 0x91, 0xb5, 0x0d, 0x7f, 0x11, 0x91, 0xb5, 0x1d, 0x7f, 0x16, 0x91, 0xb5, 0x0d, 0x7f, 0x17,
0x91, 0xb5, 0x90, 0xff, 0x50, 0x74, 0x03, 0xf0, 0x90, 0xff, 0x68, 0xf0, 0xc2, 0xaf, 0x7d, 0x06,
0x7f, 0x10, 0x51, 0xdb, 0x7d, 0x06, 0x7f, 0x17, 0xb1, 0x1e, 0x7d, 0x02, 0x7f, 0x10, 0x51, 0xdb,
0x7d, 0x02, 0x7f, 0x17, 0x51, 0xdb, 0x7d, 0x02, 0x51, 0xd9, 0x7d, 0x02, 0xb1, 0x08, 0xe4, 0xfa,
0x0a, 0xba, 0xff, 0xfc, 0xc2, 0xaf, 0x7d, 0x07, 0x51, 0xd9, 0xb1, 0x06, 0x90, 0xff, 0x55, 0x74,
0x14, 0xf1, 0x0e, 0x90, 0xff, 0x50, 0x74, 0x07, 0xd1, 0xfa, 0xb1, 0x0f, 0x90, 0xff, 0x52, 0xe0,
0xff, 0xa3, 0xe0, 0x90, 0x00, 0xdf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x5a, 0xe0, 0xff,
0xa3, 0xe0, 0x90, 0x00, 0xe1, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x62, 0xe0, 0xff, 0xa3,
0xe0, 0x90, 0x00, 0xe3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x6a, 0xe0, 0xff, 0xa3, 0xe0,
0x90, 0x00, 0xe5, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x22, 0x7f, 0x11, 0x11, 0xb7, 0xd2, 0xaf, 0xc2,
0xaf, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0,
0x00, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x91, 0xff, 0xc2, 0xaf, 0x90,
0x04, 0x53, 0x71, 0xc9, 0x7d, 0x05, 0x51, 0xdb, 0x90, 0x04, 0x54, 0x71, 0xc9, 0x7d, 0x05, 0x51,
0xdb, 0x90, 0x04, 0x55, 0x71, 0xc9, 0x7d, 0x05, 0x51, 0xdb, 0x90, 0x04, 0x56, 0x71, 0xc9, 0x7d,
0x05, 0xd1, 0xee, 0x90, 0x04, 0x53, 0x91, 0xdf, 0x90, 0xff, 0x5a, 0xe0, 0xfe, 0xa3, 0xe0, 0xff,
0x90, 0x04, 0x54, 0x91, 0xe0, 0x90, 0xff, 0x62, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x04, 0x55,
0x91, 0xe0, 0x90, 0xff, 0x6a, 0xe0, 0xfe, 0xa3, 0xe0, 0x90, 0x04, 0x56, 0x91, 0xdf, 0xd5, 0x1c,
0x0c, 0x90, 0xff, 0x4a, 0xe4, 0xf0, 0x90, 0xff, 0x50, 0xd1, 0xfa, 0x80, 0x55, 0x90, 0x04, 0x53,
0xe0, 0x24, 0x02, 0xf0, 0x90, 0x04, 0x55, 0xe0, 0x24, 0x02, 0xf0, 0x90, 0x04, 0x53, 0xe0, 0x04,
0xa3, 0xf0, 0xa3, 0xe0, 0x04, 0xa3, 0xf0, 0x75, 0x54, 0x64, 0x75, 0x55, 0x00, 0xf1, 0x08, 0x7d,
0x03, 0xed, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x50, 0xb1, 0x66, 0xe0, 0x20, 0xe7, 0x0d, 0x74, 0x01,
0xa8, 0x05, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x55, 0xaf, 0x05, 0x1d, 0xef, 0x70,
0xe0, 0xe5, 0x55, 0x64, 0x0f, 0x60, 0x07, 0xaf, 0x54, 0x15, 0x54, 0xef, 0x70, 0xd1, 0x11, 0x7f,
0x11, 0x69, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x00, 0xd0, 0xd0,
0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xe0, 0xff, 0xe5, 0x1f, 0x24, 0x06, 0xf5,
0x82, 0xe4, 0x35, 0x1e, 0xf5, 0x83, 0xe5, 0x82, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83,
0xe4, 0x93, 0xff, 0x22, 0x75, 0x1e, 0x07, 0x75, 0x1f, 0x36, 0x78, 0x8d, 0x7c, 0x00, 0x7a, 0x07,
0x79, 0x64, 0x7f, 0x08, 0x12, 0x3a, 0x25, 0x90, 0x07, 0x64, 0xe4, 0x93, 0x78, 0x8d, 0xf6, 0x43,
0x95, 0x80, 0x90, 0xff, 0x41, 0x74, 0x07, 0xf0, 0xe4, 0x90, 0xff, 0x87, 0xf0, 0x90, 0xff, 0x4b,
0x74, 0x13, 0xf0, 0x90, 0xff, 0x4b, 0xe0, 0x30, 0xe3, 0xf9, 0x90, 0xff, 0x49, 0x74, 0x05, 0xf0,
0xe4, 0xfd, 0x7f, 0x11, 0xb1, 0x37, 0x7d, 0x01, 0x7f, 0x11, 0x91, 0xb5, 0xc2, 0xaf, 0x0d, 0x51,
0xd9, 0x7d, 0x07, 0x7f, 0x11, 0x11, 0xb7, 0xd2, 0xaf, 0xe4, 0xfd, 0x7f, 0x16, 0xb1, 0x37, 0xe4,
0xfd, 0x7f, 0x16, 0x91, 0xb5, 0xc2, 0xaf, 0x7d, 0x02, 0x7f, 0x16, 0x51, 0xdb, 0xb1, 0x06, 0xe4,
0xf5, 0x1c, 0xf5, 0x19, 0xf5, 0x1d, 0xf5, 0x1a, 0x20, 0x06, 0x1f, 0xfe, 0x7f, 0x2a, 0xfd, 0x7b,
0x01, 0x7a, 0x02, 0x79, 0x09, 0x12, 0x04, 0xdf, 0x7f, 0x54, 0x7b, 0x01, 0x7a, 0x00, 0x79, 0x8b,
0xf1, 0x36, 0x75, 0x23, 0x05, 0x75, 0x24, 0x01, 0x80, 0x0c, 0x75, 0x23, 0x02, 0xe4, 0xf5, 0x24,
0x90, 0xff, 0x87, 0x74, 0x03, 0xf0, 0xe4, 0xfb, 0xb1, 0x70, 0x2b, 0xf5, 0x82, 0xe4, 0x35, 0x83,
0xf5, 0x83, 0xe4, 0x93, 0xf5, 0x25, 0xeb, 0x54, 0x01, 0x55, 0x24, 0xfd, 0xaf, 0x25, 0x91, 0xb5,
0xad, 0x24, 0xaf, 0x25, 0xb1, 0x37, 0xc2, 0xaf, 0xad, 0x23, 0xaf, 0x25, 0x11, 0xb7, 0xd2, 0xaf,
0x0b, 0xbb, 0x24, 0xd4, 0x22, 0x12, 0x39, 0xf7, 0x90, 0xff, 0x13, 0xd3, 0x94, 0x03, 0x40, 0x0f,
0xef, 0x75, 0xf0, 0x04, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0xed,
0x60, 0x04, 0xe0, 0x4c, 0xf0, 0x22, 0xe0, 0xff, 0xec, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x22, 0xff,
0xe0, 0x25, 0xe0, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef,
0xf0, 0x22, 0xff, 0xea, 0x25, 0xe0, 0x24, 0xdf, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x22, 0xf0, 0x90,
0xff, 0x43, 0x74, 0x9f, 0xf0, 0x22, 0x7d, 0x07, 0x7f, 0x16, 0x11, 0xb7, 0xd2, 0xaf, 0x22, 0x90,
0xff, 0x40, 0x74, 0x09, 0xf0, 0x90, 0xff, 0x43, 0xe0, 0x30, 0xe4, 0xf9, 0x80, 0xe1, 0x11, 0xb7,
0xd2, 0xaf, 0xb1, 0x0f, 0xc2, 0xaf, 0x22, 0x25, 0xe0, 0x24, 0x61, 0xf5, 0x82, 0xe4, 0x34, 0x01,
0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0x22, 0x12, 0x39, 0xf7, 0xc2, 0xaf, 0x75, 0xa0, 0xff, 0xbf,
0x01, 0x04, 0x7e, 0x18, 0x80, 0x08, 0xef, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x12, 0xfe, 0xed, 0xa8,
0x06, 0x60, 0x05, 0xe2, 0x4c, 0xf2, 0x80, 0x08, 0xe2, 0xff, 0xec, 0xf4, 0xfd, 0xef, 0x5d, 0xf2,
0xe4, 0xf5, 0xa0, 0xd2, 0xaf, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0xff, 0x8f, 0x82, 0xf5, 0x83, 0x22,
0xe5, 0x1f, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x1e, 0xf5, 0x83, 0xe5, 0x82, 0x22, 0xab, 0x05,
0xef, 0x14, 0xfa, 0xc2, 0xaf, 0xb1, 0x70, 0x2a, 0x71, 0xd9, 0xad, 0x03, 0x11, 0xb7, 0xd2, 0xaf,
0xaf, 0x02, 0x1a, 0xef, 0x70, 0xed, 0x22, 0xa9, 0x07, 0xb9, 0xa5, 0x0a, 0x75, 0x88, 0x08, 0x75,
0x89, 0x80, 0x91, 0xff, 0xc1, 0x75, 0x75, 0x91, 0x01, 0xe4, 0xf5, 0x91, 0x30, 0x05, 0x10, 0xe9,
0x54, 0xe0, 0x60, 0x0b, 0xd1, 0x75, 0xe4, 0xf5, 0x91, 0x7d, 0x05, 0x7f, 0x24, 0xb1, 0x7e, 0x22,
0x75, 0x22, 0xff, 0x75, 0x5f, 0x01, 0xe5, 0x62, 0x70, 0x0c, 0xc2, 0x06, 0x71, 0xe4, 0x12, 0x18,
0x0d, 0x75, 0x62, 0x01, 0xc1, 0x64, 0xe5, 0x62, 0x64, 0x01, 0x70, 0x65, 0x78, 0x9a, 0xf6, 0x12,
0x30, 0x04, 0x7f, 0x7b, 0x12, 0x18, 0x32, 0x20, 0x00, 0x1c, 0xe5, 0x56, 0x70, 0x18, 0x05, 0x60,
0xe5, 0x60, 0xd3, 0x94, 0x64, 0x40, 0x1d, 0x75, 0x60, 0x64, 0xe5, 0x63, 0x7f, 0x14, 0x60, 0x02,
0x7f, 0x1e, 0x8f, 0x61, 0x80, 0x0e, 0xe4, 0xf5, 0x60, 0x12, 0x39, 0x5e, 0x7f, 0x0b, 0x40, 0x02,
0x7f, 0x1e, 0x8f, 0x61, 0xc2, 0x05, 0xe5, 0x63, 0x60, 0x18, 0x7f, 0x7b, 0x12, 0x37, 0x11, 0x8f,
0x22, 0x7f, 0x0c, 0x7a, 0x00, 0x79, 0x7b, 0x12, 0x39, 0x8b, 0xe4, 0x78, 0x9a, 0xf6, 0xd2, 0x05,
0x80, 0x06, 0xe4, 0x78, 0x64, 0xf6, 0x08, 0xf6, 0x7f, 0x7b, 0xad, 0x22, 0x12, 0x31, 0x80, 0x80,
0x23, 0xe5, 0x62, 0xb4, 0x02, 0x06, 0x7f, 0xa5, 0xb1, 0x97, 0x80, 0x18, 0xe5, 0x62, 0xb4, 0x03,
0x10, 0xd2, 0x06, 0x71, 0xe4, 0x31, 0x07, 0xe4, 0xf5, 0x62, 0x00, 0xe4, 0x78, 0x99, 0xf6, 0x80,
0xf9, 0xe4, 0xf5, 0x62, 0xf1, 0x1c, 0xe5, 0x5f, 0x60, 0x0a, 0xaf, 0x22, 0xb1, 0x97, 0xe4, 0x78,
0x99, 0xf6, 0x80, 0xf2, 0x22, 0xe4, 0xfd, 0x7f, 0x24, 0xb1, 0x7e, 0x75, 0x91, 0x03, 0x22, 0x78,
0x8d, 0xe6, 0xf5, 0x34, 0x76, 0x04, 0x75, 0x33, 0x3c, 0xe4, 0xf5, 0x35, 0x78, 0x99, 0xf6, 0xff,
0xe5, 0x33, 0xb4, 0x3c, 0x04, 0xd1, 0xd8, 0xe4, 0xf0, 0xd1, 0xd8, 0xe0, 0x24, 0x02, 0xf0, 0x0f,
0xef, 0xc3, 0x94, 0x24, 0x40, 0xea, 0x11, 0x18, 0xf1, 0x1c, 0xe4, 0xff, 0xef, 0xb1, 0x27, 0xc3,
0x94, 0x99, 0xec, 0x94, 0x01, 0x50, 0x08, 0xd1, 0xd8, 0xe0, 0x24, 0xfe, 0xf0, 0x05, 0x35, 0x0f,
0xef, 0xc3, 0x94, 0x24, 0x40, 0xe6, 0xe5, 0x35, 0x94, 0x24, 0x50, 0x07, 0xaf, 0x33, 0x15, 0x33,
0xef, 0x70, 0xb6, 0x78, 0x8d, 0xa6, 0x34, 0x22, 0x74, 0x37, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01,
0xf5, 0x83, 0x22, 0x74, 0x53, 0x2b, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0xf5, 0x83, 0x22, 0x11, 0xb7,
0xd2, 0xaf, 0x90, 0xff, 0x52, 0xe0, 0xfe, 0xa3, 0xe0, 0x22, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x90,
0xff, 0x60, 0xf0, 0x90, 0xff, 0x68, 0xf0, 0x22, 0x78, 0x91, 0xe6, 0x90, 0xff, 0x55, 0xf0, 0x90,
0xff, 0x5d, 0xf0, 0x90, 0xff, 0x65, 0xf0, 0x90, 0xff, 0x6d, 0xf0, 0x22, 0xe5, 0x1c, 0x60, 0x03,
0x00, 0x80, 0xf9, 0x78, 0x61, 0x7c, 0x01, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x02, 0x79, 0x33, 0x7e,
0x00, 0x7f, 0x54, 0x02, 0x00, 0xf4, 0x7e, 0x00, 0x7d, 0x00, 0x02, 0x04, 0xdf, 0xf1, 0x1c, 0x11,
0x18, 0xe4, 0xf5, 0x37, 0xf5, 0x38, 0xf5, 0x39, 0xf5, 0x3a, 0x90, 0x03, 0x32, 0xf0, 0xa3, 0xf0,
0xf5, 0x34, 0xf5, 0x33, 0xf5, 0x32, 0x12, 0x39, 0xa0, 0xe0, 0xf5, 0x3b, 0xa3, 0xe0, 0xf5, 0x3c,
0x12, 0x39, 0xa0, 0xc0, 0x83, 0xc0, 0x82, 0xae, 0x3b, 0xaf, 0x3c, 0x12, 0x17, 0x73, 0xc3, 0xa3,
0xe0, 0x9f, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x9e, 0xd0, 0x82,
0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x3a, 0x19, 0x12, 0x17, 0x6c, 0xff, 0x12, 0x17, 0x7a,
0x12, 0x39, 0xa0, 0x12, 0x3a, 0x2e, 0x12, 0x3a, 0x19, 0xf5, 0x83, 0x12, 0x3a, 0x6c, 0x12, 0x17,
0x61, 0xff, 0xe5, 0x32, 0xb1, 0x27, 0xc3, 0x9f, 0xf5, 0x36, 0xec, 0x9e, 0xf5, 0x35, 0xe5, 0x32,
0x12, 0x13, 0x8c, 0xe4, 0xf0, 0xa3, 0xf0, 0xc3, 0x12, 0x17, 0xa1, 0x40, 0x4a, 0xe5, 0x32, 0xd3,
0x94, 0x0f, 0xe5, 0x32, 0x40, 0x06, 0x54, 0x01, 0x24, 0x86, 0x80, 0x04, 0x54, 0x01, 0x24, 0x84,
0xf8, 0xe2, 0xff, 0xe4, 0x8f, 0x44, 0xf5, 0x43, 0xf5, 0x42, 0xf5, 0x41, 0xab, 0x44, 0xaa, 0x43,
0xa9, 0x42, 0xa8, 0x41, 0xae, 0x35, 0xaf, 0x36, 0x12, 0x24, 0x3e, 0x12, 0x24, 0x28, 0x8c, 0x41,
0xe4, 0x7b, 0x80, 0xfa, 0xf9, 0xf8, 0x12, 0x03, 0x6c, 0x12, 0x24, 0x28, 0x8c, 0x41, 0xe5, 0x32,
0x71, 0x8c, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x39, 0xaf, 0x3a, 0xf1, 0x73, 0xe5, 0x3a, 0x2f,
0xff, 0xe5, 0x39, 0x3e, 0xfe, 0xc3, 0xef, 0x95, 0x36, 0xe5, 0x35, 0xf1, 0x81, 0x50, 0x09, 0x85,
0x32, 0x33, 0x85, 0x35, 0x39, 0x85, 0x36, 0x3a, 0xd3, 0xe5, 0x38, 0x95, 0x36, 0xe5, 0x35, 0x64,
0x80, 0xf8, 0xe5, 0x37, 0x64, 0x80, 0x98, 0x40, 0x06, 0x85, 0x35, 0x37, 0x85, 0x36, 0x38, 0xf1,
0x61, 0xff, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0xdb, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0x12, 0x0d, 0x30,
0xc3, 0x9f, 0xff, 0xec, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0xd3, 0xef, 0x94, 0x13, 0xee, 0x94, 0x05,
0x40, 0x03, 0x43, 0x1a, 0x10, 0xb1, 0x39, 0x50, 0x03, 0x02, 0x0f, 0x56, 0xe4, 0xf5, 0x3d, 0xf5,
0x3e, 0xf5, 0x3f, 0xf5, 0x40, 0x90, 0x03, 0x31, 0xf0, 0xf5, 0x32, 0xe5, 0x32, 0x25, 0xe0, 0xb1,
0x41, 0xf1, 0x6c, 0xff, 0xe5, 0x32, 0x25, 0xe0, 0x71, 0x8c, 0xe0, 0xfc, 0xa3, 0xe0, 0x2f, 0xff,
0xec, 0x3e, 0xf8, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x5a, 0xc8, 0xf2, 0x08, 0xef, 0xf2, 0xd1, 0x5c,
0xd3, 0x94, 0xb1, 0xee, 0x94, 0x01, 0x40, 0x1e, 0xe5, 0x32, 0x94, 0x08, 0x50, 0x0e, 0xef, 0x95,
0x3e, 0xee, 0x95, 0x3d, 0x40, 0x15, 0x8e, 0x3d, 0x8f, 0x3e, 0x80, 0x0f, 0xf1, 0x89, 0x40, 0x0b,
0x8e, 0x3f, 0x8f, 0x40, 0x80, 0x05, 0xef, 0x25, 0x34, 0xf5, 0x34, 0x05, 0x32, 0xe5, 0x32, 0x64,
0x10, 0x70, 0xa8, 0xe5, 0x34, 0x75, 0xf0, 0x32, 0x84, 0xf5, 0x34, 0xe4, 0xf5, 0x32, 0xe5, 0x32,
0xc3, 0x94, 0x10, 0x50, 0x06, 0xae, 0x3d, 0xaf, 0x3e, 0x80, 0x04, 0xae, 0x3f, 0xaf, 0x40, 0x8e,
0x3b, 0x8f, 0x3c, 0xe5, 0x32, 0x71, 0x8c, 0xf1, 0xa8, 0x40, 0x1b, 0xf1, 0x73, 0xc3, 0xeb, 0x9f,
0xea, 0x9e, 0x50, 0x12, 0xe5, 0x32, 0xc3, 0x94, 0x10, 0x50, 0x05, 0x90, 0x03, 0x32, 0x80, 0x03,
0x90, 0x03, 0x33, 0xe0, 0x04, 0xf0, 0xf1, 0x2a, 0x50, 0x06, 0xae, 0x3d, 0xaf, 0x3e, 0x80, 0x04,
0xae, 0x3f, 0xaf, 0x40, 0x8e, 0x3b, 0x8f, 0x3c, 0xe5, 0x32, 0x71, 0x8c, 0xf1, 0xa8, 0x40, 0x29,
0x12, 0x3a, 0x46, 0xc3, 0xeb, 0x9f, 0xea, 0x9e, 0x50, 0x1f, 0xe5, 0x32, 0x71, 0x8c, 0xe0, 0xfe,
0xa3, 0xe0, 0xff, 0xe5, 0x32, 0xb1, 0x41, 0x12, 0x0d, 0x30, 0xfd, 0xf1, 0xf3, 0xef, 0xc3, 0x94,
0x1e, 0x50, 0x06, 0x90, 0x03, 0x31, 0xe0, 0x04, 0xf0, 0xe5, 0x32, 0x71, 0x8c, 0xe0, 0xfe, 0xa3,
0xe0, 0xff, 0x4e, 0x60, 0x28, 0xad, 0x34, 0x7c, 0x00, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x10,
0xe5, 0x32, 0x71, 0x8c, 0xe0, 0xfe, 0xa3, 0xe0, 0xc3, 0x9d, 0xff, 0xee, 0x9c, 0xfe, 0x80, 0x04,
0x7e, 0x00, 0x7f, 0x01, 0xe5, 0x32, 0x71, 0x8c, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xb1, 0x39, 0x50,
0x02, 0x01, 0xde, 0xf1, 0x2a, 0x50, 0x06, 0xae, 0x3d, 0xaf, 0x3e, 0x80, 0x04, 0xae, 0x3f, 0xaf,
0x40, 0x8e, 0x3b, 0x8f, 0x3c, 0xc3, 0x90, 0x03, 0x30, 0xe0, 0x95, 0x3c, 0x90, 0x03, 0x2f, 0xe0,
0x95, 0x3b, 0x50, 0x03, 0x12, 0x3a, 0x6c, 0xe5, 0x13, 0x70, 0x0e, 0xae, 0x3b, 0xaf, 0x3c, 0xfc,
0x7d, 0x19, 0x12, 0x01, 0xd9, 0x8e, 0x14, 0x8f, 0x15, 0x75, 0x3b, 0x00, 0x75, 0x3c, 0x0a, 0xc3,
0xe5, 0x3e, 0x95, 0x40, 0xff, 0xe5, 0x3d, 0x95, 0x3f, 0xfe, 0x12, 0x00, 0x12, 0xaa, 0x06, 0xab,
0x07, 0xe5, 0x3e, 0x25, 0x40, 0xff, 0xe5, 0x3d, 0x35, 0x3f, 0xfe, 0xf1, 0x7a, 0xef, 0x78, 0x02,
0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xc3, 0xeb, 0x9f, 0xea, 0x9e, 0x50, 0x0c, 0x20,
0x03, 0x09, 0x74, 0x04, 0x25, 0x3c, 0xf5, 0x3c, 0xe4, 0x80, 0x0b, 0x30, 0x03, 0x0c, 0x74, 0xfc,
0x25, 0x3c, 0xf5, 0x3c, 0x74, 0xff, 0x35, 0x3b, 0xf5, 0x3b, 0x90, 0x03, 0x31, 0xe0, 0xff, 0xd3,
0x95, 0x3c, 0xe5, 0x3b, 0x64, 0x80, 0xf8, 0x74, 0x80, 0x98, 0x40, 0x2d, 0xe5, 0x13, 0x94, 0x05,
0x50, 0x08, 0x74, 0x03, 0x25, 0x13, 0xf5, 0x13, 0x80, 0x03, 0x75, 0x13, 0x50, 0xe5, 0x11, 0xb4,
0x02, 0x17, 0x53, 0x1a, 0xf7, 0x90, 0x00, 0xcd, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0xa3, 0xe4, 0xf0,
0xa3, 0x04, 0xf0, 0xa3, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0xd3, 0xf1, 0x91, 0x40, 0x21, 0xe5, 0x33,
0x25, 0xe0, 0x24, 0x89, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x12, 0x0d, 0x30, 0x4c, 0x70, 0x0a, 0xe5,
0x33, 0xb1, 0x41, 0x12, 0x0d, 0x30, 0x4c, 0x60, 0x06, 0x75, 0x1d, 0x28, 0x43, 0x1a, 0x08, 0xef,
0xd3, 0x94, 0x05, 0x40, 0x1c, 0xe5, 0x3a, 0x94, 0xdc, 0xe5, 0x39, 0x64, 0x80, 0x94, 0x85, 0x50,
0x10, 0xf1, 0x91, 0x40, 0x0c, 0xe5, 0x56, 0x70, 0x02, 0xf5, 0x1d, 0x20, 0x00, 0x03, 0x53, 0x1a,
0xf7, 0xc3, 0xe4, 0x95, 0x38, 0xff, 0xe4, 0x95, 0x37, 0xfe, 0xc3, 0x74, 0x13, 0x9f, 0xee, 0x64,
0x80, 0xf8, 0x74, 0x05, 0x64, 0x80, 0x98, 0x50, 0x10, 0x74, 0x62, 0x95, 0x3a, 0xe5, 0x39, 0x64,
0x80, 0xf8, 0x74, 0x03, 0x64, 0x80, 0x98, 0x50, 0x0d, 0x90, 0x03, 0x31, 0xe0, 0xd3, 0x94, 0x1b,
0x40, 0x0a, 0xe5, 0x56, 0x70, 0x06, 0x43, 0x1a, 0x10, 0x75, 0x1d, 0x01, 0xe5, 0x1d, 0x60, 0x02,
0x61, 0x75, 0xf5, 0x32, 0xf1, 0x61, 0xff, 0xe5, 0x32, 0x12, 0x0d, 0x27, 0xc3, 0x9f, 0xf5, 0x36,
0xec, 0x9e, 0xf5, 0x35, 0xf1, 0x55, 0xe0, 0xff, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x12, 0x2f, 0x2a,
0xf5, 0x35, 0xfe, 0x7d, 0x02, 0x12, 0x3a, 0x0d, 0xf1, 0x55, 0xef, 0xf0, 0x12, 0x00, 0x12, 0xd3,
0xef, 0x94, 0x28, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x2d, 0xae, 0x35, 0x7d, 0x14, 0x12, 0x3a,
0x0d, 0x12, 0x00, 0x12, 0xd3, 0xef, 0x94, 0x90, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x12, 0xf1,
0x9c, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x90, 0x80, 0x04, 0x7e, 0xff, 0x7f, 0x70, 0x8e, 0x35, 0x8f,
0x36, 0xf1, 0x55, 0xe4, 0xf0, 0x80, 0x12, 0xf1, 0x9c, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80,
0x04, 0x7e, 0xff, 0x7f, 0xff, 0x8e, 0x35, 0x8f, 0x36, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0xb5, 0xf5,
0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe5, 0x35, 0x85, 0x36, 0xf0, 0x12, 0x02, 0x0f, 0xb1, 0x39,
0x50, 0x02, 0x41, 0xe4, 0x22, 0x15, 0x1d, 0x22, 0xe5, 0x36, 0x25, 0xe0, 0x24, 0x8b, 0xf5, 0x82,
0xe4, 0x34, 0x00, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x35, 0x25, 0xe0, 0x24, 0x8b,
0xf5, 0x82, 0xe4, 0x34, 0x00, 0xf5, 0x83, 0x22, 0x8f, 0x32, 0xe5, 0x32, 0x25, 0xe0, 0xf5, 0x35,
0x04, 0xf5, 0x36, 0xe5, 0x35, 0x24, 0xfe, 0xf5, 0x33, 0xe5, 0x35, 0x14, 0xf5, 0x34, 0xe5, 0x35,
0x24, 0x02, 0xf5, 0x37, 0xe5, 0x35, 0x24, 0x03, 0xf5, 0x38, 0xe5, 0x32, 0xd3, 0x94, 0x07, 0x40,
0x18, 0x71, 0x8a, 0xf1, 0x1a, 0x71, 0x8c, 0xd1, 0xdf, 0xf1, 0x34, 0x40, 0x46, 0xe5, 0x3b, 0x13,
0xfe, 0xe5, 0x3c, 0x13, 0xff, 0xe5, 0x35, 0x80, 0x35, 0x71, 0x78, 0xd1, 0xdf, 0xe5, 0x32, 0xd3,
0x94, 0x01, 0x40, 0x09, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x56, 0x12, 0x39, 0xc4, 0xe5, 0x32, 0xc3,
0x94, 0x06, 0x50, 0x09, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x5e, 0x12, 0x39, 0xc4, 0xf1, 0x34, 0x40,
0x12, 0xae, 0x3b, 0xaf, 0x3c, 0x7c, 0x00, 0x7d, 0x03, 0x12, 0x01, 0x84, 0xe5, 0x36, 0x71, 0x8c,
0x12, 0x3a, 0x2e, 0xaf, 0x32, 0xd1, 0xa6, 0xef, 0x64, 0x01, 0x70, 0x5a, 0xd1, 0x5c, 0xe5, 0x32,
0x25, 0xe0, 0x24, 0x5c, 0xf1, 0x42, 0xb1, 0x31, 0xe5, 0x32, 0x70, 0x17, 0x85, 0x36, 0x44, 0x7b,
0x5a, 0x7d, 0x19, 0x91, 0xe5, 0x71, 0x78, 0xb1, 0x15, 0x24, 0xf1, 0xff, 0x85, 0x36, 0x44, 0x7b,
0x78, 0x80, 0x2f, 0xaf, 0x3a, 0x85, 0x36, 0x44, 0x7b, 0x6e, 0x7d, 0x19, 0x91, 0xe5, 0xe5, 0x37,
0x71, 0x8c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x38, 0x71, 0x8c, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd,
0xb1, 0x31, 0x7b, 0x28, 0x7a, 0x00, 0x7d, 0x14, 0xb1, 0x27, 0x24, 0xec, 0xff, 0x85, 0x35, 0x44,
0x7b, 0x64, 0x7d, 0x64, 0x91, 0xe5, 0xaf, 0x32, 0xd1, 0xa6, 0xef, 0x64, 0x02, 0x70, 0x36, 0xd1,
0x5c, 0xe5, 0x32, 0xf1, 0x3e, 0xb1, 0x31, 0xe5, 0x32, 0x64, 0x0f, 0x70, 0x1d, 0x85, 0x35, 0x44,
0x7b, 0x50, 0x7d, 0x19, 0x91, 0xe5, 0x71, 0x8a, 0xf1, 0x1a, 0x71, 0x8c, 0xb1, 0x15, 0x24, 0xf1,
0xff, 0x85, 0x35, 0x44, 0x7b, 0x32, 0x7d, 0x64, 0x80, 0x09, 0xaf, 0x3a, 0x85, 0x35, 0x44, 0x7b,
0x82, 0x7d, 0x18, 0x91, 0xe5, 0x22, 0xab, 0x07, 0xaa, 0x06, 0xaf, 0x05, 0xae, 0x04, 0x12, 0x24,
0x2f, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e, 0xfc, 0xaf, 0x03, 0xae, 0x02, 0x12, 0x01, 0x84, 0xaa,
0x06, 0xab, 0x07, 0xd3, 0xeb, 0x94, 0xc8, 0xea, 0x94, 0x00, 0xaf, 0x03, 0x40, 0x02, 0x7f, 0xc8,
0x22, 0x7b, 0x28, 0x7d, 0x32, 0x8b, 0x43, 0xef, 0xd3, 0x9d, 0x40, 0x02, 0xaf, 0x05, 0xe5, 0x44,
0x71, 0x8c, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x7e, 0x00, 0x12, 0x04, 0xb2, 0xc0, 0x07, 0xaf, 0x43,
0xab, 0x07, 0xe4, 0xfa, 0xf9, 0xf8, 0xd0, 0x07, 0x12, 0x03, 0x6c, 0xe5, 0x44, 0x71, 0x8c, 0xee,
0x8f, 0xf0, 0x02, 0x02, 0x0f, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x91, 0xb6, 0x75, 0x39, 0x00, 0x8f,
0x3a, 0x7b, 0x50, 0x7a, 0x00, 0x7d, 0x0f, 0xae, 0x39, 0xd1, 0xbd, 0x8e, 0x39, 0x8f, 0x3a, 0xef,
0x22, 0x91, 0xb6, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x22, 0x05, 0x32, 0xe5, 0x32, 0xc3, 0x94, 0x24,
0x22, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x22, 0x8f, 0x32, 0x8d, 0x33, 0x85,
0x32, 0x34, 0xe4, 0xf5, 0x38, 0xf5, 0x36, 0xf5, 0x3d, 0xf5, 0x3e, 0x75, 0x37, 0xff, 0xe5, 0x34,
0xc3, 0x95, 0x33, 0x40, 0x02, 0xc1, 0x18, 0xe5, 0x34, 0x25, 0xe0, 0xf5, 0x35, 0xaf, 0x34, 0xd1,
0xa6, 0x8f, 0x39, 0xe5, 0x39, 0x60, 0x35, 0xb4, 0x01, 0x0c, 0xe5, 0x34, 0xd1, 0x5e, 0xe5, 0x34,
0x25, 0xe0, 0x24, 0x5c, 0x80, 0x0a, 0xe5, 0x34, 0xd1, 0x5e, 0xe5, 0x34, 0x25, 0xe0, 0x24, 0x58,
0xf1, 0x42, 0x91, 0xb6, 0x8f, 0x39, 0xe5, 0x39, 0x24, 0x03, 0xff, 0x85, 0x35, 0x44, 0x91, 0xe1,
0xe5, 0x39, 0x24, 0x03, 0xff, 0xe5, 0x35, 0x04, 0xf5, 0x44, 0x91, 0xe1, 0xe5, 0x35, 0xb1, 0x41,
0x71, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0x2f, 0xf5, 0x40, 0xec, 0x3e, 0xf5, 0x3f, 0xd3, 0xf1, 0x2b,
0x40, 0x16, 0xd3, 0xe5, 0x40, 0x94, 0xb1, 0xe5, 0x3f, 0x94, 0x01, 0x40, 0x0b, 0x75, 0x38, 0x01,
0x85, 0x3f, 0x3d, 0x85, 0x40, 0x3e, 0x80, 0x39, 0xae, 0x3d, 0xaf, 0x3e, 0x7c, 0x00, 0x7d, 0x07,
0x12, 0x01, 0x84, 0xc3, 0xe5, 0x3e, 0x9f, 0xff, 0xe5, 0x3d, 0x9e, 0xfe, 0xf1, 0x89, 0x40, 0x24,
0xe5, 0x38, 0x60, 0x0d, 0xe4, 0xf5, 0x38, 0x12, 0x39, 0xae, 0xe5, 0x36, 0xc3, 0x94, 0x03, 0x50,
0x17, 0xae, 0x3f, 0xaf, 0x40, 0xf1, 0x7a, 0xe5, 0x40, 0x2f, 0xf5, 0x3e, 0xe5, 0x3f, 0x3e, 0xf5,
0x3d, 0x85, 0x34, 0x37, 0x05, 0x34, 0xa1, 0x5e, 0xe5, 0x38, 0x60, 0x0a, 0xe5, 0x36, 0xc3, 0x94,
0x02, 0x50, 0x03, 0x12, 0x39, 0xae, 0x7b, 0xff, 0xf1, 0xb4, 0xb4, 0xff, 0x04, 0x7f, 0xff, 0x80,
0x02, 0xf1, 0x22, 0xe5, 0x32, 0x7e, 0x02, 0x70, 0x01, 0xfe, 0x74, 0x95, 0x2e, 0xf8, 0xa6, 0x07,
0xab, 0x34, 0xf1, 0xb4, 0xb4, 0xff, 0x04, 0x7f, 0xff, 0x80, 0x02, 0xf1, 0x22, 0xe5, 0x32, 0x7e,
0x03, 0x70, 0x02, 0x7e, 0x01, 0x74, 0x95, 0x2e, 0xf8, 0xa6, 0x07, 0x22, 0xe5, 0x32, 0x25, 0xe0,
0x24, 0x5a, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x22, 0x7d, 0x01, 0xe4, 0xff, 0x8f, 0x3b, 0x8d,
0x3c, 0xe5, 0x3c, 0x75, 0xf0, 0x1f, 0xa4, 0x24, 0x15, 0xd1, 0x62, 0xe5, 0x3b, 0x75, 0xf0, 0x07,
0xa4, 0x24, 0x40, 0xf1, 0x49, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3c, 0x75, 0xf0, 0x1f, 0xa4, 0x24,
0x17, 0xd1, 0x62, 0xe5, 0x3b, 0x75, 0xf0, 0x07, 0xa4, 0x24, 0x42, 0xf1, 0x49, 0xd0, 0xe0, 0x2f,
0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0x22, 0xef, 0x60, 0x03, 0xbf, 0x08, 0x03, 0x7f, 0x01, 0x22, 0xef,
0x64, 0x07, 0x60, 0x03, 0xbf, 0x0f, 0x03, 0x7f, 0x02, 0x22, 0x7f, 0x00, 0x22, 0xed, 0xf5, 0x82,
0x75, 0x83, 0x00, 0xc3, 0xef, 0x95, 0x82, 0x74, 0x80, 0xf8, 0x6e, 0x98, 0x50, 0x04, 0x7e, 0x00,
0xaf, 0x82, 0xd3, 0xef, 0x9b, 0xea, 0xf1, 0x81, 0x40, 0x04, 0xae, 0x02, 0xaf, 0x03, 0x22, 0xe0,
0xfc, 0xa3, 0xe0, 0xfd, 0x91, 0xb6, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x90, 0x00, 0xce, 0xe0, 0x25,
0xe0, 0xff, 0x90, 0x00, 0xcd, 0xe0, 0x33, 0xfe, 0x90, 0x00, 0xd0, 0xe0, 0x2f, 0xfd, 0x90, 0x00,
0xcf, 0xe0, 0x3e, 0xfc, 0x90, 0x00, 0xd2, 0xe0, 0x25, 0xe0, 0xff, 0x90, 0x00, 0xd1, 0xe0, 0x33,
0xfe, 0xed, 0x2f, 0xf5, 0x3c, 0xec, 0x3e, 0xf5, 0x3b, 0x22, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5,
0x36, 0x22, 0x74, 0x3a, 0x25, 0x34, 0xf8, 0xe6, 0xff, 0x22, 0xc3, 0xe5, 0x40, 0x95, 0x3e, 0xe5,
0x3f, 0x95, 0x3d, 0x22, 0xd3, 0xe5, 0x3a, 0x94, 0x14, 0xe5, 0x39, 0x94, 0x00, 0x22, 0x25, 0xe0,
0x24, 0x58, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0x22, 0xf8, 0xc3, 0xe2, 0x9f, 0xff, 0x18, 0xe2,
0x9e, 0xfe, 0x02, 0x00, 0x12, 0x74, 0x09, 0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83,
0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0xfe,
0xa3, 0xe0, 0x22, 0x7c, 0x00, 0x7d, 0x05, 0x02, 0x01, 0xd9, 0x7c, 0x00, 0x7d, 0x05, 0x02, 0x01,
0x84, 0x64, 0x80, 0xf8, 0xee, 0x64, 0x80, 0x98, 0x22, 0xd3, 0xef, 0x95, 0x40, 0xee, 0x95, 0x3f,
0x22, 0xe5, 0x3a, 0x94, 0xb1, 0xe5, 0x39, 0x64, 0x80, 0x94, 0x81, 0x22, 0xd3, 0xe5, 0x36, 0x94,
0x00, 0xe5, 0x35, 0x64, 0x80, 0x94, 0x80, 0x22, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0xd3, 0x94, 0xc8,
0xea, 0x94, 0x00, 0x22, 0x7f, 0x87, 0xad, 0x36, 0xf1, 0xbf, 0x8f, 0x34, 0xe5, 0x34, 0x22, 0xa9,
0x05, 0xe4, 0xfe, 0xfd, 0xfc, 0x7a, 0xff, 0xee, 0xc3, 0x99, 0x50, 0x24, 0xee, 0x6b, 0x60, 0x1b,
0xa8, 0x07, 0xe6, 0xf5, 0x83, 0x08, 0xe6, 0xf5, 0x82, 0xd3, 0x9d, 0xe5, 0x83, 0x9c, 0x40, 0x0b,
0xe5, 0x82, 0x24, 0x20, 0xfd, 0xe4, 0x35, 0x83, 0xfc, 0xaa, 0x06, 0x0e, 0x0f, 0x0f, 0x80, 0xd7,
0xaf, 0x02, 0x22, 0x8e, 0x45, 0x8f, 0x46, 0xd3, 0xe5, 0x46, 0x9d, 0xe5, 0x45, 0x9c, 0x40, 0x02,
0x80, 0x08, 0xaf, 0x05, 0xae, 0x04, 0xad, 0x46, 0xac, 0x45, 0x02, 0x14, 0xb6, 0x7f, 0x03, 0x7b,
0xfe, 0x7a, 0x00, 0x79, 0x88, 0x11, 0x2b, 0xe4, 0xf5, 0x10, 0xf5, 0x1b, 0xf5, 0x12, 0xc2, 0x01,
0xd2, 0x02, 0xc2, 0x03, 0xc2, 0x04, 0x90, 0x04, 0x57, 0xf0, 0x22, 0x7e, 0x00, 0x7d, 0x00, 0x02,
0x04, 0xdf, 0x8f, 0x23, 0x7f, 0x0c, 0xa9, 0x23, 0x7a, 0x00, 0x7b, 0x00, 0x11, 0x2b, 0x7f, 0x1c,
0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x3e, 0xd1, 0xd1, 0xe5, 0x10, 0x14, 0x60, 0x32, 0x04, 0x60, 0x02,
0x61, 0x92, 0xe4, 0xf5, 0x1b, 0xf5, 0x13, 0xf5, 0x11, 0xb1, 0xf5, 0xc2, 0x00, 0xfe, 0x7f, 0x3e,
0xfd, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x00, 0x12, 0x04, 0xdf, 0x12, 0x07, 0xe5, 0x75, 0x10, 0x01,
0x7e, 0x00, 0x7f, 0x04, 0x7d, 0xff, 0x7b, 0x01, 0x7a, 0x04, 0x79, 0x45, 0x02, 0x04, 0xdf, 0xe4,
0xf5, 0x1a, 0x12, 0x0f, 0x3d, 0xc2, 0x01, 0xe5, 0x1a, 0x30, 0xe4, 0x20, 0x05, 0x1b, 0xe5, 0x1b,
0xc3, 0x94, 0x0e, 0x40, 0x0d, 0x53, 0x1a, 0xf7, 0xe5, 0x1b, 0xb4, 0x0f, 0x05, 0xe4, 0xf5, 0x10,
0xf5, 0x1b, 0xe5, 0x11, 0xb4, 0x02, 0x08, 0x53, 0x1a, 0xf7, 0x80, 0x03, 0xe4, 0xf5, 0x1b, 0xc2,
0x07, 0xe4, 0xf5, 0x2e, 0xf5, 0x2f, 0xf5, 0x2a, 0xf5, 0x2b, 0xe5, 0x56, 0x70, 0x02, 0x21, 0x5f,
0xe4, 0xf5, 0x30, 0xf5, 0x31, 0x75, 0x24, 0x01, 0xe5, 0x24, 0x12, 0x16, 0x5e, 0xd3, 0x94, 0xb4,
0xee, 0x94, 0x00, 0x40, 0x12, 0x05, 0x31, 0xe5, 0x24, 0x12, 0x17, 0x3e, 0x12, 0x17, 0xf3, 0xef,
0xc3, 0x94, 0x32, 0x50, 0x02, 0x05, 0x30, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x5a, 0xb1, 0xda, 0xce,
0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x25, 0x2f, 0xf5, 0x2f, 0xee, 0x35, 0x2e, 0xf5, 0x2e, 0xe5,
0x24, 0x25, 0xe0, 0x24, 0x6a, 0xb1, 0xda, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x25, 0x2b,
0xf5, 0x2b, 0xee, 0x35, 0x2a, 0xf5, 0x2a, 0x05, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x08, 0x40, 0xa8,
0xe5, 0x56, 0xb4, 0x02, 0x0e, 0xe5, 0x31, 0xd3, 0x94, 0x02, 0x40, 0x02, 0xd2, 0x07, 0x53, 0x1a,
0xf7, 0x80, 0x2c, 0xe5, 0x30, 0xd3, 0x94, 0x04, 0x50, 0x11, 0xe5, 0x2f, 0x94, 0xd0, 0xe5, 0x2e,
0x94, 0x07, 0x40, 0x1b, 0xe5, 0x30, 0xd3, 0x94, 0x02, 0x40, 0x14, 0xe5, 0x2a, 0xc3, 0x13, 0xfe,
0xe5, 0x2b, 0x13, 0xff, 0xd3, 0xe5, 0x2f, 0x9f, 0xe5, 0x2e, 0x9e, 0x40, 0x02, 0xd2, 0x07, 0xe5,
0x1a, 0x20, 0xe3, 0x02, 0x61, 0x50, 0x7d, 0x08, 0xe4, 0xff, 0x12, 0x15, 0x4b, 0x7d, 0x10, 0x7f,
0x08, 0x12, 0x15, 0x4b, 0x75, 0x17, 0x3e, 0xe4, 0xf5, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x04, 0x50,
0x3b, 0x74, 0x95, 0x25, 0x24, 0xf8, 0xe6, 0xa8, 0x17, 0xf2, 0xc3, 0x94, 0x10, 0x50, 0x27, 0xe8,
0xd1, 0xda, 0x7d, 0xff, 0x91, 0x2c, 0x74, 0x95, 0x25, 0x24, 0xf8, 0xe6, 0xff, 0x12, 0x13, 0x98,
0x7d, 0xff, 0xb1, 0xec, 0x91, 0x34, 0xb1, 0xcb, 0x70, 0x0c, 0xa8, 0x17, 0x74, 0xff, 0xf2, 0x74,
0x95, 0x25, 0x24, 0xf8, 0x76, 0xff, 0x05, 0x24, 0x91, 0x1b, 0x80, 0xbe, 0xe4, 0xf5, 0x26, 0xf5,
0x27, 0xf5, 0x28, 0xf5, 0x29, 0x75, 0x17, 0x3e, 0xf5, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x02, 0x40,
0x02, 0x41, 0xe1, 0x74, 0x26, 0x25, 0x24, 0xf8, 0xe6, 0x60, 0x02, 0x41, 0xdb, 0x75, 0x18, 0x4c,
0x75, 0x25, 0x02, 0xe5, 0x25, 0xc3, 0x94, 0x04, 0x40, 0x02, 0x41, 0xdb, 0x74, 0x26, 0x25, 0x25,
0xf8, 0xe6, 0x60, 0x02, 0x41, 0xd1, 0xa8, 0x17, 0xe2, 0xf4, 0x70, 0x02, 0x41, 0xd1, 0xa8, 0x18,
0xe2, 0xf4, 0x70, 0x02, 0x41, 0xd1, 0xe8, 0x04, 0x12, 0x16, 0x62, 0xe5, 0x17, 0x24, 0x02, 0x12,
0x17, 0x49, 0x8e, 0x2a, 0x8f, 0x2b, 0x75, 0x31, 0x0a, 0x75, 0x30, 0x0a, 0xe5, 0x11, 0xb4, 0x01,
0x06, 0x75, 0x31, 0x05, 0x75, 0x30, 0x05, 0xe5, 0x17, 0x24, 0x03, 0x12, 0x16, 0x62, 0xe5, 0x18,
0x24, 0x04, 0xf8, 0xc3, 0xe2, 0x9f, 0xf5, 0x2d, 0x18, 0xe2, 0x9e, 0xf5, 0x2c, 0xe5, 0x30, 0x7e,
0x01, 0x7f, 0xe0, 0xb1, 0xd2, 0xe5, 0x2b, 0x9f, 0xe5, 0x2a, 0x9e, 0x50, 0x4b, 0xe5, 0x31, 0x7e,
0x03, 0x7f, 0xc0, 0xb1, 0xd2, 0xe5, 0x2d, 0x9f, 0xe5, 0x2c, 0x9e, 0x50, 0x3b, 0xa8, 0x17, 0xe2,
0xff, 0xa8, 0x18, 0xe2, 0xfd, 0x71, 0x96, 0xef, 0xf4, 0x60, 0x25, 0xe5, 0x2c, 0xc3, 0x13, 0xe5,
0x2d, 0x13, 0x90, 0x04, 0x58, 0xf0, 0xad, 0x25, 0x91, 0x2c, 0xad, 0x25, 0xb1, 0xec, 0x91, 0x34,
0x74, 0x26, 0x25, 0x24, 0xf8, 0x76, 0x01, 0x74, 0x26, 0x25, 0x25, 0xf8, 0x76, 0x01, 0x80, 0x04,
0xa8, 0x17, 0x91, 0x22, 0xa8, 0x18, 0x80, 0x37, 0xa8, 0x17, 0xe2, 0x91, 0x14, 0xf5, 0x2c, 0x08,
0xe2, 0xf5, 0x2d, 0xa8, 0x18, 0xe2, 0x91, 0x14, 0xf5, 0x2e, 0x08, 0xe2, 0xf5, 0x2f, 0xfd, 0xac,
0x2e, 0xaf, 0x2d, 0xae, 0x2c, 0x12, 0x17, 0xf3, 0xef, 0xd3, 0x94, 0x32, 0x40, 0x13, 0xd3, 0xe5,
0x2d, 0x95, 0x2f, 0xe5, 0x2c, 0x95, 0x2e, 0x40, 0x04, 0xa8, 0x18, 0x80, 0x02, 0xa8, 0x17, 0x91,
0x22, 0x05, 0x25, 0x74, 0x07, 0x25, 0x18, 0xf5, 0x18, 0x21, 0xe3, 0x05, 0x24, 0x91, 0x1b, 0x21,
0xca, 0x75, 0x17, 0x3e, 0xe4, 0xf5, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x02, 0x50, 0x62, 0x74, 0x26,
0x25, 0x24, 0xf8, 0xe6, 0x70, 0x54, 0xa8, 0x17, 0xe2, 0xff, 0xf4, 0x60, 0x0d, 0x7d, 0xff, 0x71,
0x96, 0xa8, 0x17, 0xef, 0xf2, 0xbf, 0xff, 0x02, 0x91, 0x25, 0xa8, 0x17, 0xe2, 0xf4, 0x70, 0x3a,
0x75, 0x18, 0x4c, 0x75, 0x25, 0x02, 0xe5, 0x25, 0xc3, 0x94, 0x04, 0x50, 0x2d, 0x74, 0x26, 0x25,
0x25, 0xf8, 0xe6, 0x70, 0x1b, 0xa8, 0x18, 0xe2, 0xff, 0xf4, 0x60, 0x14, 0x7d, 0xff, 0x71, 0x96,
0xa8, 0x18, 0xef, 0xf2, 0xf4, 0x60, 0x09, 0xb1, 0xae, 0xa8, 0x18, 0x74, 0xff, 0xf2, 0x80, 0x0a,
0x05, 0x25, 0x74, 0x07, 0x25, 0x18, 0xf5, 0x18, 0x80, 0xcc, 0x05, 0x24, 0x91, 0x1b, 0x80, 0x97,
0xe5, 0x13, 0x60, 0x04, 0x15, 0x13, 0x80, 0x03, 0xe4, 0xb1, 0xf5, 0xe5, 0x12, 0x60, 0x02, 0x15,
0x12, 0xc2, 0x00, 0x75, 0x17, 0x3e, 0x75, 0x18, 0x45, 0x91, 0x3b, 0x12, 0x24, 0x8c, 0xa8, 0x23,
0x7c, 0x00, 0x7d, 0x00, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x3f, 0xd1, 0xea, 0xe5, 0x23, 0x24, 0x06,
0xf8, 0x7c, 0x00, 0x7d, 0x00, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x46, 0x7e, 0x00, 0x7f, 0x06, 0x02,
0x00, 0xf4, 0xe4, 0xf5, 0x10, 0x22, 0x8f, 0x32, 0xef, 0x91, 0x14, 0xfe, 0x08, 0xe2, 0xfb, 0xaa,
0x06, 0xed, 0xf4, 0x60, 0x0b, 0xed, 0x91, 0x14, 0xfe, 0x08, 0xe2, 0x2b, 0xfb, 0xee, 0x3a, 0xfa,
0x90, 0x03, 0xe8, 0xaf, 0x32, 0x12, 0x16, 0xa6, 0xbf, 0x01, 0x0a, 0x78, 0x68, 0xe2, 0xfe, 0x08,
0xe2, 0x78, 0x79, 0xd1, 0x22, 0xaf, 0x32, 0x12, 0x16, 0xa6, 0xbf, 0x02, 0x0a, 0x78, 0x6a, 0xe2,
0xfe, 0x08, 0xe2, 0x78, 0x5b, 0xd1, 0x22, 0xe5, 0x15, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0x14, 0x35,
0x83, 0xf5, 0x83, 0x30, 0x04, 0x03, 0x75, 0x12, 0x14, 0xe5, 0x12, 0x60, 0x19, 0xe5, 0x13, 0x70,
0x15, 0xfc, 0x7d, 0x03, 0xaf, 0x82, 0xae, 0x83, 0x12, 0x01, 0x84, 0xc3, 0xe5, 0x82, 0x9f, 0xf5,
0x82, 0xe5, 0x83, 0x9e, 0xf5, 0x83, 0xc3, 0xeb, 0x95, 0x82, 0xea, 0x95, 0x83, 0xaf, 0x32, 0x50,
0x02, 0x7f, 0xff, 0x22, 0x25, 0xe0, 0x24, 0x5a, 0xf8, 0xe2, 0x22, 0x74, 0x07, 0x25, 0x17, 0xf5,
0x17, 0x22, 0x74, 0xff, 0xf2, 0xe8, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0x22, 0xaf, 0x24, 0x12, 0x21,
0xa7, 0xe5, 0x17, 0x04, 0xf8, 0xee, 0xf2, 0x08, 0xef, 0xf2, 0x22, 0xe4, 0xf5, 0x33, 0xf5, 0x34,
0xf5, 0x32, 0xb1, 0xcb, 0x70, 0x11, 0xe5, 0x18, 0x24, 0x05, 0xf8, 0xe2, 0x60, 0x09, 0xb1, 0xae,
0xe5, 0x18, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0xb1, 0xcb, 0x60, 0x02, 0x05, 0x33, 0xe5, 0x18, 0x24,
0x05, 0xf8, 0xe2, 0x60, 0x02, 0x05, 0x33, 0x78, 0x1d, 0xe2, 0xff, 0x60, 0x02, 0x05, 0x34, 0x78,
0x3c, 0xe2, 0x60, 0x02, 0x05, 0x34, 0xe5, 0x33, 0x70, 0x03, 0x30, 0x01, 0x02, 0xd2, 0x00, 0x75,
0x35, 0x00, 0x75, 0x36, 0xb4, 0x90, 0x04, 0x57, 0xe0, 0xfe, 0x70, 0x04, 0xe5, 0x13, 0x60, 0x0f,
0x75, 0x35, 0x01, 0x75, 0x36, 0x2c, 0xee, 0x60, 0x06, 0x90, 0x04, 0x57, 0xe0, 0x14, 0xf0, 0xe5,
0x33, 0x64, 0x01, 0x70, 0x69, 0xe5, 0x34, 0x70, 0x02, 0xa1, 0x84, 0xe5, 0x34, 0x64, 0x01, 0x70,
0x45, 0xef, 0x60, 0x1e, 0xe4, 0xfd, 0xb1, 0xa5, 0x78, 0x0b, 0xd1, 0x00, 0x50, 0x06, 0x75, 0x39,
0x00, 0x75, 0x3a, 0x0a, 0xb1, 0xe2, 0x50, 0x02, 0xa1, 0x84, 0xd1, 0x0f, 0x50, 0x02, 0xa1, 0x84,
0xa1, 0x81, 0x78, 0x3c, 0xe2, 0x70, 0x02, 0xa1, 0x84, 0x7d, 0x01, 0xe4, 0xb1, 0xa5, 0x78, 0x2a,
0xd1, 0x00, 0x50, 0x06, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x0a, 0xb1, 0xe2, 0x40, 0x06, 0xd1, 0x0f,
0x40, 0x02, 0xa1, 0x84, 0xa1, 0x81, 0xe5, 0x34, 0x64, 0x02, 0x60, 0x02, 0xa1, 0x84, 0xfd, 0xb1,
0xa5, 0x12, 0x16, 0x69, 0x8e, 0x39, 0x8f, 0x3a, 0xb1, 0xc1, 0x40, 0x78, 0x80, 0x73, 0xe5, 0x33,
0x64, 0x02, 0x70, 0x70, 0xe5, 0x34, 0x60, 0x6c, 0xe5, 0x34, 0x64, 0x01, 0x70, 0x26, 0x78, 0x1d,
0xe2, 0x60, 0x0a, 0xe4, 0xfd, 0xb1, 0xa5, 0xe4, 0xfd, 0x7f, 0x01, 0x80, 0x0a, 0x7d, 0x01, 0x7f,
0x01, 0xb1, 0xa6, 0x7d, 0x01, 0xe4, 0xff, 0x12, 0x16, 0x6d, 0x8e, 0x39, 0x8f, 0x3a, 0xb1, 0xc1,
0x40, 0x42, 0x80, 0x3d, 0xe5, 0x34, 0x64, 0x02, 0x70, 0x3a, 0x7d, 0x01, 0x7f, 0x01, 0x12, 0x16,
0x6d, 0xc0, 0x06, 0xc0, 0x07, 0xe4, 0xfd, 0xff, 0x12, 0x16, 0x6d, 0xd0, 0xe0, 0x2f, 0xf5, 0x38,
0xd0, 0xe0, 0x3e, 0xf5, 0x37, 0xe4, 0xfd, 0x7f, 0x01, 0x12, 0x16, 0x6d, 0xc0, 0x06, 0xc0, 0x07,
0x12, 0x16, 0x69, 0xd0, 0xe0, 0x2f, 0xf5, 0x3a, 0xd0, 0xe0, 0x3e, 0xf5, 0x39, 0xb1, 0xc1, 0x40,
0x03, 0x75, 0x32, 0x01, 0xe5, 0x32, 0x60, 0x1c, 0xa9, 0x17, 0x7a, 0x00, 0x7b, 0xfe, 0xe5, 0x18,
0x24, 0x07, 0xf8, 0xb1, 0xb6, 0xb1, 0xae, 0xe5, 0x18, 0x24, 0x07, 0xf9, 0x7a, 0x00, 0x7b, 0xfe,
0xa8, 0x18, 0xb1, 0xb6, 0x22, 0xff, 0x12, 0x16, 0x6d, 0x8e, 0x37, 0x8f, 0x38, 0x22, 0xa9, 0x18,
0x7a, 0x00, 0x7b, 0xfe, 0xa8, 0x17, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x07, 0x02, 0x00,
0xf4, 0xd3, 0xe5, 0x38, 0x95, 0x3a, 0xe5, 0x37, 0x95, 0x39, 0x22, 0xe5, 0x17, 0x24, 0x05, 0xf8,
0xe2, 0x22, 0xfd, 0x7c, 0x00, 0x12, 0x01, 0x84, 0xc3, 0x22, 0xf9, 0xe3, 0xfe, 0x09, 0xe3, 0x78,
0x03, 0x22, 0xd3, 0xe5, 0x38, 0x95, 0x36, 0xe5, 0x37, 0x95, 0x35, 0x22, 0xaf, 0x24, 0xf1, 0xcc,
0xe5, 0x17, 0x24, 0x03, 0x22, 0xf5, 0x14, 0xf5, 0x15, 0x90, 0x03, 0x2f, 0xf0, 0xa3, 0xf0, 0x22,
0xe2, 0xf5, 0x39, 0x08, 0xe2, 0xf5, 0x3a, 0xc3, 0x94, 0x0a, 0xe5, 0x39, 0x94, 0x00, 0x22, 0xae,
0x39, 0xaf, 0x3a, 0x7c, 0x00, 0x7d, 0x06, 0x12, 0x01, 0x72, 0xd3, 0xe5, 0x38, 0x9f, 0xe5, 0x37,
0x9e, 0x22, 0xff, 0xe2, 0x2f, 0xff, 0x18, 0xe2, 0x3e, 0xc3, 0x13, 0xfe, 0xef, 0x13, 0x24, 0x84,
0xf5, 0x82, 0xee, 0x34, 0x03, 0xf5, 0x83, 0x22, 0xab, 0x07, 0xaa, 0x05, 0x90, 0x00, 0x01, 0xeb,
0x91, 0x14, 0xf5, 0x45, 0x08, 0xe2, 0xf5, 0x46, 0xaf, 0x03, 0x12, 0x16, 0xa6, 0xbf, 0x01, 0x10,
0xe5, 0x82, 0x64, 0x01, 0x45, 0x83, 0x70, 0x67, 0xea, 0x64, 0x01, 0x70, 0x62, 0x0b, 0x80, 0x5f,
0xaf, 0x03, 0x12, 0x16, 0xa6, 0xbf, 0x02, 0x0f, 0xe5, 0x82, 0x64, 0x01, 0x45, 0x83, 0x70, 0x4f,
0xea, 0xf4, 0x70, 0x4b, 0x1b, 0x80, 0x48, 0xeb, 0x91, 0x14, 0xf5, 0x47, 0x08, 0xe2, 0xf5, 0x48,
0xea, 0x2b, 0xfb, 0xae, 0x45, 0xaf, 0x46, 0x7c, 0x00, 0x7d, 0x1e, 0x12, 0x01, 0x84, 0xeb, 0x25,
0xe0, 0x24, 0x5a, 0x12, 0x17, 0x42, 0xd3, 0x9f, 0xec, 0x9e, 0x40, 0x10, 0xe5, 0x48, 0x24, 0xc8,
0xff, 0xe4, 0x35, 0x47, 0xfe, 0xd3, 0xed, 0x9f, 0xec, 0x9e, 0x40, 0x06, 0xc3, 0xeb, 0x9a, 0xfb,
0x80, 0x0d, 0xe5, 0x82, 0x15, 0x82, 0xae, 0x83, 0x70, 0x02, 0x15, 0x83, 0x4e, 0x70, 0x89, 0xd3,
0xea, 0x64, 0x80, 0x94, 0x80, 0x7f, 0x00, 0x40, 0x02, 0x7f, 0x01, 0xef, 0x2b, 0x25, 0xe0, 0xff,
0x22, 0x7e, 0x00, 0x7d, 0x00, 0x02, 0x04, 0xdf, 0xe5, 0x17, 0x24, 0x05, 0xf8, 0x74, 0x01, 0xf2,
0x22, 0x7a, 0x00, 0x7b, 0xfe, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x06, 0x02, 0x00,
0xf4, 0xe4, 0xff, 0xfe, 0xfd, 0xfc, 0x78, 0x6a, 0x12, 0x04, 0x64, 0xc3, 0x12, 0x04, 0x21, 0x60,
0x08, 0x78, 0x6e, 0xe6, 0xd3, 0x94, 0x05, 0x40, 0x03, 0x7f, 0xff, 0x22, 0x7f, 0x16, 0x7b, 0x00,
0x7a, 0x00, 0x79, 0x2c, 0xd1, 0xd1, 0xe4, 0xf5, 0x2a, 0x78, 0x6e, 0xe6, 0xff, 0xd3, 0x94, 0x00,
0x40, 0x1a, 0xef, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0, 0xfb, 0x78, 0x6a, 0x12, 0x04, 0x58, 0xa8,
0x03, 0x12, 0x04, 0x32, 0xef, 0x54, 0x0f, 0xff, 0x8f, 0x4c, 0x80, 0x03, 0xe4, 0xf5, 0x4c, 0xe4,
0xf5, 0x2b, 0x74, 0x2c, 0x25, 0x2b, 0xf8, 0xe6, 0x70, 0x63, 0xe5, 0x2b, 0x75, 0xf0, 0x0a, 0xa4,
0x24, 0x16, 0xf5, 0x82, 0xe4, 0x34, 0x06, 0xf5, 0x83, 0x75, 0xf0, 0x02, 0xe5, 0x2a, 0x12, 0x04,
0x96, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfd, 0xac, 0x06, 0x54, 0x0f, 0xab, 0x4c, 0x6b, 0x70,
0x01, 0xe4, 0x60, 0x2f, 0xec, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0xed, 0xc4, 0x54, 0x0f, 0x48, 0x54,
0x0f, 0x6b, 0x70, 0x01, 0xe4, 0x60, 0x1c, 0xec, 0x54, 0x0f, 0x6b, 0x70, 0x01, 0xe4, 0x60, 0x13,
0xec, 0xc4, 0x54, 0x0f, 0x6b, 0x70, 0x01, 0xe4, 0x60, 0x09, 0x74, 0x2c, 0x25, 0x2b, 0xf8, 0x76,
0x01, 0x80, 0x0a, 0xe5, 0x2a, 0xb4, 0x04, 0x05, 0xe5, 0x2b, 0x04, 0xff, 0x22, 0x05, 0x2b, 0xe5,
0x2b, 0x64, 0x16, 0x70, 0x8d, 0x78, 0x6e, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x01, 0x16, 0x05, 0x2a,
0xe5, 0x2a, 0xd3, 0x94, 0x04, 0x50, 0x02, 0xe1, 0x19, 0x7f, 0xff, 0x22, 0x8f, 0x32, 0x8d, 0x33,
0xe4, 0xf5, 0x3b, 0xf5, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xf5, 0x3f, 0xf5, 0x3e, 0xf5, 0x3d, 0xf5,
0x3c, 0x85, 0x32, 0x35, 0xe5, 0x35, 0x12, 0x23, 0xe3, 0xf9, 0xff, 0x7d, 0xff, 0xd1, 0x38, 0x8f,
0x34, 0xaf, 0x01, 0x7d, 0x01, 0xd1, 0x38, 0x8f, 0x44, 0xe5, 0x33, 0xf4, 0x60, 0x28, 0xe9, 0x14,
0xf5, 0x34, 0xe9, 0x24, 0x02, 0xf5, 0x44, 0xaf, 0x01, 0x12, 0x16, 0xa6, 0xbf, 0x01, 0x04, 0x89,
0x34, 0x80, 0x07, 0xbf, 0x02, 0x04, 0xe9, 0x04, 0xf5, 0x44, 0xe5, 0x34, 0x25, 0xe0, 0xf5, 0x34,
0xe5, 0x44, 0x25, 0xe0, 0xf5, 0x44, 0x90, 0x04, 0x58, 0xe0, 0xff, 0xd3, 0x94, 0x14, 0x40, 0x02,
0x80, 0x02, 0x7f, 0x14, 0x75, 0x42, 0x00, 0x8f, 0x43, 0xae, 0x42, 0x7d, 0x07, 0x31, 0x8f, 0xef,
0x25, 0x43, 0xf5, 0x43, 0xee, 0x35, 0x42, 0xf5, 0x42, 0xe5, 0x34, 0xc3, 0x95, 0x44, 0x50, 0x7d,
0x75, 0xf0, 0x02, 0xe5, 0x34, 0x90, 0x06, 0xf6, 0x12, 0x04, 0x96, 0xe4, 0x93, 0xf5, 0x40, 0x74,
0x01, 0x93, 0xf5, 0x41, 0xe5, 0x33, 0xf4, 0x60, 0x2a, 0xe5, 0x34, 0xc3, 0x94, 0x10, 0x50, 0x11,
0xc3, 0x90, 0x06, 0xf2, 0x74, 0x01, 0x93, 0x95, 0x43, 0xff, 0xe4, 0x93, 0x95, 0x42, 0xfe, 0x80,
0x0e, 0x90, 0x06, 0xf4, 0x74, 0x01, 0x93, 0x25, 0x43, 0xff, 0xe4, 0x93, 0x35, 0x42, 0xfe, 0x8e,
0x40, 0x8f, 0x41, 0xe5, 0x34, 0x12, 0x13, 0x8c, 0xe0, 0xf5, 0x36, 0xa3, 0xe0, 0xf5, 0x37, 0xff,
0xe4, 0xfc, 0xfd, 0xe5, 0x3f, 0x2f, 0xff, 0xe5, 0x3e, 0x35, 0x36, 0xfe, 0xed, 0x35, 0x3d, 0xfd,
0xec, 0x35, 0x3c, 0x8f, 0x3f, 0x8e, 0x3e, 0x8d, 0x3d, 0xf5, 0x3c, 0xae, 0x36, 0xaf, 0x37, 0x91,
0x36, 0xae, 0x40, 0xaf, 0x41, 0x91, 0x3e, 0x91, 0x10, 0x05, 0x34, 0x01, 0x49, 0xe5, 0x35, 0x65,
0x33, 0x60, 0x0b, 0xe5, 0x33, 0xf4, 0x60, 0x06, 0x85, 0x33, 0x35, 0x02, 0x1f, 0xe4, 0xe4, 0x7b,
0x02, 0xfa, 0xf9, 0xf8, 0xaf, 0x3f, 0xae, 0x3e, 0xad, 0x3d, 0xac, 0x3c, 0x12, 0x05, 0xa8, 0x91,
0x10, 0xfc, 0xab, 0x3f, 0xaa, 0x3e, 0xa9, 0x3d, 0xa8, 0x3c, 0x12, 0x05, 0xa8, 0x8f, 0x3b, 0x8e,
0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x8e, 0x36, 0x8f, 0x37, 0xe5, 0x33, 0xf4, 0x70, 0x3b, 0xf5, 0x42,
0x75, 0x43, 0x05, 0xe5, 0x32, 0x71, 0xe3, 0xc3, 0x94, 0x08, 0x50, 0x16, 0xc3, 0x74, 0xe0, 0x95,
0x43, 0xff, 0x74, 0x01, 0x95, 0x42, 0xfe, 0xd3, 0xe5, 0x37, 0x9f, 0xe5, 0x36, 0x9e, 0x40, 0x19,
0x80, 0x13, 0xe5, 0x43, 0x24, 0xe0, 0xff, 0xe5, 0x42, 0x34, 0x01, 0xfe, 0xc3, 0xe5, 0x37, 0x9f,
0xe5, 0x36, 0x9e, 0x50, 0x04, 0x8e, 0x36, 0x8f, 0x37, 0xac, 0x38, 0xec, 0x33, 0x50, 0x1e, 0x74,
0xff, 0x7f, 0x9c, 0xfe, 0xfd, 0xfc, 0xab, 0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xc3, 0x12,
0x04, 0x0b, 0x50, 0x02, 0x31, 0x9b, 0xe4, 0xf5, 0x36, 0xf5, 0x37, 0x80, 0x1d, 0xc3, 0xe5, 0x37,
0x94, 0xc0, 0xe5, 0x36, 0x94, 0x03, 0x40, 0x12, 0xe5, 0x37, 0x94, 0x24, 0xe5, 0x36, 0x94, 0x04,
0x40, 0x02, 0x31, 0x9b, 0x75, 0x36, 0x03, 0x75, 0x37, 0xbf, 0xae, 0x36, 0xaf, 0x37, 0x22, 0x7c,
0x00, 0x12, 0x01, 0xd9, 0x7c, 0x00, 0x7d, 0x03, 0x02, 0x01, 0x72, 0xe5, 0x35, 0x75, 0xf0, 0x07,
0xa4, 0x24, 0x43, 0xf8, 0xe4, 0xf2, 0x22, 0x8d, 0x32, 0xab, 0x07, 0xe4, 0xf5, 0x44, 0xf5, 0x43,
0xf5, 0x42, 0xf5, 0x41, 0xf5, 0x48, 0xf5, 0x47, 0xf5, 0x46, 0xf5, 0x45, 0x8b, 0x33, 0xe5, 0x33,
0x71, 0xe3, 0xf5, 0x49, 0xf5, 0x4a, 0xe5, 0x4a, 0xc3, 0x94, 0x08, 0x40, 0x06, 0x74, 0xf8, 0x25,
0x4a, 0xf5, 0x4a, 0xe5, 0x49, 0x25, 0xe0, 0x24, 0x58, 0xf8, 0xe2, 0xf5, 0x35, 0x08, 0xe2, 0xf5,
0x36, 0xe5, 0x49, 0x12, 0x1c, 0x14, 0xf5, 0x37, 0x08, 0xe2, 0xf5, 0x38, 0xe5, 0x49, 0x25, 0xe0,
0x24, 0x5c, 0xf8, 0xe2, 0xf5, 0x39, 0x08, 0xe2, 0xf5, 0x3a, 0x30, 0x02, 0x05, 0x71, 0xdb, 0xff,
0x80, 0x1e, 0xae, 0x37, 0xaf, 0x38, 0x91, 0x2f, 0x7c, 0x00, 0x7d, 0x09, 0x12, 0x01, 0x72, 0xaa,
0x06, 0xab, 0x07, 0x71, 0xdb, 0xff, 0x0d, 0x12, 0x01, 0x84, 0xeb, 0x2f, 0xff, 0xea, 0x3e, 0xfe,
0xab, 0x07, 0xaa, 0x06, 0xe5, 0x4a, 0x70, 0x4f, 0x30, 0x02, 0x05, 0xfe, 0x7f, 0x20, 0x80, 0x04,
0x7e, 0x00, 0x7f, 0x30, 0x8e, 0x3f, 0x8f, 0x40, 0xae, 0x39, 0xaf, 0x3a, 0x71, 0xfc, 0x50, 0x0b,
0xc3, 0xe5, 0x3a, 0x94, 0x2c, 0xe5, 0x39, 0x94, 0x01, 0x50, 0x06, 0xd2, 0x01, 0xe5, 0x33, 0x31,
0x9d, 0x12, 0x1d, 0xc1, 0x40, 0x17, 0xe5, 0x38, 0x95, 0x3a, 0xff, 0xe5, 0x37, 0x95, 0x39, 0xfe,
0x7c, 0x00, 0x7d, 0x06, 0x12, 0x01, 0x72, 0x1d, 0x12, 0x01, 0x84, 0x80, 0x04, 0x7e, 0x00, 0x7f,
0x00, 0x8e, 0x35, 0x8f, 0x36, 0x80, 0x63, 0xe5, 0x4a, 0x64, 0x07, 0x70, 0x44, 0x30, 0x02, 0x05,
0xfe, 0x7f, 0x20, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x30, 0x8e, 0x3f, 0x8f, 0x40, 0xae, 0x35, 0xaf,
0x36, 0x71, 0xfc, 0x50, 0x0b, 0xc3, 0xe5, 0x36, 0x94, 0x90, 0xe5, 0x35, 0x94, 0x01, 0x50, 0x06,
0xd2, 0x01, 0xe5, 0x33, 0x31, 0x9d, 0x12, 0x1d, 0xe2, 0x40, 0x0c, 0xe5, 0x38, 0x95, 0x36, 0xff,
0xe5, 0x37, 0x95, 0x35, 0xfe, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x8e, 0x39, 0x8f, 0x3a, 0x80,
0x19, 0xe5, 0x38, 0xae, 0x37, 0x78, 0x03, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xc3,
0xe5, 0x38, 0x9f, 0xf5, 0x38, 0xe5, 0x37, 0x9e, 0xf5, 0x37, 0xe4, 0xf5, 0x34, 0xe5, 0x4a, 0x25,
0x34, 0xf5, 0x4f, 0xff, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xfe, 0x74,
0xa1, 0x2f, 0xf5, 0x82, 0x74, 0x07, 0x3e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff,
0xe4, 0x8f, 0x4e, 0x8e, 0x4d, 0xf5, 0x4c, 0xf5, 0x4b, 0xab, 0x4e, 0xaa, 0x4d, 0xa9, 0x4c, 0xa8,
0x4b, 0xc0, 0x00, 0x71, 0xec, 0xd0, 0x00, 0x12, 0x02, 0xe1, 0x8f, 0x4e, 0x8e, 0x4d, 0x8d, 0x4c,
0x8c, 0x4b, 0xe5, 0x48, 0x25, 0x4e, 0xff, 0xe5, 0x47, 0x35, 0x4d, 0xfe, 0xe5, 0x46, 0x35, 0x4c,
0xfd, 0xe5, 0x45, 0x35, 0x4b, 0x71, 0xd4, 0xf5, 0x45, 0x71, 0xec, 0xe5, 0x44, 0x2f, 0xff, 0xe5,
0x43, 0x3e, 0xfe, 0xed, 0x35, 0x42, 0xfd, 0xec, 0x35, 0x41, 0x91, 0x28, 0xf5, 0x41, 0x05, 0x34,
0xe5, 0x34, 0x64, 0x03, 0x70, 0x87, 0xe5, 0x33, 0xb5, 0x32, 0x02, 0x80, 0x0c, 0xe5, 0x32, 0xb4,
0xff, 0x02, 0x80, 0x05, 0x85, 0x32, 0x33, 0x21, 0xbe, 0xe4, 0x7b, 0x02, 0xfa, 0xf9, 0xf8, 0xaf,
0x44, 0xae, 0x43, 0xad, 0x42, 0xac, 0x41, 0x12, 0x03, 0x6c, 0xab, 0x48, 0xaa, 0x47, 0xa9, 0x46,
0xa8, 0x45, 0x12, 0x02, 0xd4, 0xab, 0x44, 0xaa, 0x43, 0xa9, 0x42, 0xa8, 0x41, 0x12, 0x03, 0x6c,
0x71, 0xd4, 0x8c, 0x45, 0xe4, 0x7b, 0x10, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xa8, 0x71, 0xd4, 0x8c,
0x45, 0xe5, 0x48, 0x24, 0xba, 0xff, 0xe5, 0x47, 0x34, 0xff, 0xfe, 0xe5, 0x46, 0x34, 0xff, 0xfd,
0xe5, 0x45, 0x34, 0xff, 0x71, 0xd4, 0xf5, 0x45, 0x7b, 0xdf, 0x7a, 0x01, 0xe4, 0xfd, 0x12, 0x16,
0xbd, 0xef, 0x24, 0x01, 0xff, 0xe4, 0x3e, 0xfe, 0x33, 0x95, 0xe0, 0x8f, 0x48, 0x8e, 0x47, 0xf5,
0x46, 0xf5, 0x45, 0x22, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x22, 0x90, 0x03, 0x2f, 0xe0, 0xfe,
0xa3, 0xe0, 0x22, 0x75, 0xf0, 0x07, 0xa4, 0x24, 0x3e, 0xf8, 0xe2, 0x22, 0xe5, 0x34, 0x25, 0xe0,
0x24, 0x35, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0x7c, 0x00, 0x7d, 0x0a,
0x12, 0x01, 0x84, 0xac, 0x3f, 0xad, 0x40, 0x12, 0x01, 0x72, 0xc3, 0xeb, 0x9f, 0xea, 0x9e, 0x22,
0xe5, 0x3b, 0x2f, 0xff, 0xe5, 0x3a, 0x3e, 0xfe, 0xe5, 0x39, 0x3d, 0xfd, 0xe5, 0x38, 0x3c, 0x8f,
0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0xf5, 0x38, 0x22, 0x8f, 0x44, 0x8e, 0x43, 0x8d, 0x42, 0x22, 0x7c,
0x00, 0x7d, 0x0a, 0x02, 0x01, 0x84, 0xab, 0x07, 0xaa, 0x06, 0xe4, 0xf9, 0xf8, 0x22, 0xee, 0x33,
0x95, 0xe0, 0xfd, 0xfc, 0x02, 0x02, 0xe1, 0xc3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x23, 0xed, 0x9b,
0xec, 0x9a, 0x40, 0x06, 0x8c, 0x83, 0x8d, 0x82, 0x80, 0x11, 0xc3, 0xef, 0x9b, 0xee, 0x9a, 0x40,
0x06, 0x8a, 0x83, 0x8b, 0x82, 0x80, 0x04, 0x8e, 0x83, 0x8f, 0x82, 0xae, 0x83, 0xaf, 0x82, 0x80,
0x1a, 0xc3, 0xef, 0x9b, 0xee, 0x9a, 0x40, 0x02, 0x80, 0x11, 0xc3, 0xed, 0x9b, 0xec, 0x9a, 0x40,
0x06, 0xae, 0x02, 0xaf, 0x03, 0x80, 0x04, 0xae, 0x04, 0xaf, 0x05, 0x22, 0x75, 0x16, 0x00, 0x75,
0x17, 0x3e, 0xe4, 0xf5, 0x11, 0xc2, 0x04, 0xf5, 0x32, 0xe5, 0x32, 0xc3, 0x94, 0x02, 0x40, 0x03,
0x02, 0x2e, 0xd7, 0x12, 0x1d, 0xcb, 0x70, 0x03, 0x02, 0x2d, 0x76, 0xe5, 0x17, 0x04, 0xf8, 0xe2,
0xf5, 0x41, 0x08, 0xe2, 0xf5, 0x42, 0xe5, 0x17, 0x24, 0x03, 0xf8, 0xe2, 0xf5, 0x43, 0x08, 0xe2,
0xf5, 0x44, 0xe5, 0x16, 0x04, 0xf8, 0xe2, 0xc3, 0x94, 0x05, 0x40, 0x02, 0xc1, 0xa9, 0xa8, 0x16,
0xe4, 0xf2, 0xe8, 0x12, 0x2f, 0xab, 0x04, 0xf8, 0xe2, 0xc3, 0x94, 0x02, 0x40, 0x36, 0x12, 0x39,
0x7d, 0x12, 0x3a, 0x4d, 0xff, 0xee, 0x95, 0x43, 0xfe, 0x12, 0x00, 0x12, 0xc0, 0x06, 0xc0, 0x07,
0x12, 0x39, 0x94, 0x12, 0x17, 0x6c, 0xc3, 0x95, 0x42, 0xff, 0xee, 0x95, 0x41, 0xfe, 0x12, 0x00,
0x12, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xd3, 0xef, 0x94, 0xc8, 0xee, 0x64, 0x80,
0x94, 0x80, 0x40, 0x0d, 0x12, 0x39, 0x69, 0x12, 0x3a, 0x05, 0x12, 0x39, 0xd9, 0xe4, 0xf0, 0xc1,
0x0e, 0x12, 0x39, 0x94, 0x12, 0x17, 0x6c, 0xc3, 0x95, 0x42, 0xf5, 0x34, 0xee, 0x95, 0x41, 0xf5,
0x33, 0x12, 0x39, 0x7d, 0x12, 0x3a, 0x4d, 0xf5, 0x36, 0xee, 0x95, 0x43, 0xf5, 0x35, 0xaf, 0x36,
0xfe, 0x12, 0x00, 0x12, 0x8e, 0x47, 0x8f, 0x48, 0x12, 0x3a, 0x55, 0x8e, 0x45, 0x8f, 0x46, 0xc3,
0xe5, 0x48, 0x94, 0x0c, 0xe5, 0x47, 0x94, 0x00, 0x50, 0x04, 0x7f, 0x02, 0x80, 0x1b, 0xd3, 0xe5,
0x48, 0x94, 0x2d, 0xe5, 0x47, 0x94, 0x00, 0x50, 0x0a, 0xe5, 0x46, 0x94, 0x1e, 0xe5, 0x45, 0x94,
0x00, 0x40, 0x04, 0x7f, 0xff, 0x80, 0x02, 0x7f, 0x04, 0x12, 0x39, 0xd9, 0xe0, 0x5f, 0x60, 0x07,
0xe5, 0x16, 0x04, 0xf8, 0x74, 0x04, 0xf2, 0x12, 0x39, 0xd9, 0xef, 0xf0, 0x30, 0xe3, 0x50, 0xae,
0x33, 0xaf, 0x34, 0x31, 0x94, 0x1d, 0x12, 0x01, 0xd9, 0xef, 0x25, 0x42, 0xf5, 0x4a, 0xee, 0x35,
0x41, 0xf5, 0x49, 0xae, 0x35, 0xaf, 0x36, 0x31, 0x94, 0x1d, 0x12, 0x01, 0xd9, 0xef, 0x25, 0x44,
0xf5, 0x4c, 0xee, 0x35, 0x43, 0xf5, 0x4b, 0x7b, 0xdf, 0x7a, 0x01, 0xe4, 0xfd, 0xaf, 0x4a, 0xae,
0x49, 0x12, 0x16, 0xbd, 0x8e, 0x41, 0x8f, 0x42, 0x7b, 0xbf, 0x7a, 0x03, 0xaf, 0x4c, 0xae, 0x4b,
0x12, 0x16, 0xbd, 0x8e, 0x43, 0x8f, 0x44, 0x90, 0x04, 0x57, 0x74, 0x06, 0xf0, 0x80, 0x2f, 0x12,
0x39, 0x94, 0x12, 0x17, 0x6c, 0x25, 0x42, 0xff, 0xe5, 0x41, 0x3e, 0xc3, 0x13, 0xf5, 0x41, 0xef,
0x13, 0xf5, 0x42, 0x12, 0x39, 0x7d, 0xe0, 0xfe, 0xa3, 0xe0, 0x25, 0x44, 0xff, 0xe5, 0x43, 0x3e,
0xc3, 0x13, 0xf5, 0x43, 0xef, 0x13, 0xf5, 0x44, 0x12, 0x39, 0x69, 0x12, 0x3a, 0x05, 0xe5, 0x16,
0x04, 0xf8, 0xe2, 0x04, 0xf2, 0xe5, 0x17, 0x04, 0x12, 0x39, 0xee, 0xe5, 0x17, 0x24, 0x03, 0x12,
0x39, 0xe5, 0xe5, 0x16, 0x24, 0x11, 0x12, 0x39, 0xee, 0xe5, 0x16, 0x24, 0x13, 0x12, 0x39, 0xe5,
0xe5, 0x16, 0x24, 0x0d, 0x12, 0x39, 0xee, 0xe5, 0x16, 0x24, 0x0f, 0x12, 0x39, 0xe5, 0xe5, 0x16,
0x24, 0x19, 0x12, 0x39, 0xee, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x39, 0xe5, 0xe5, 0x16, 0x24, 0x0b,
0x12, 0x2f, 0xb6, 0x24, 0x03, 0x12, 0x2f, 0xb6, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0x12,
0x2e, 0xf2, 0xf5, 0x83, 0xe4, 0xf0, 0xa3, 0xf0, 0x12, 0x2e, 0xe6, 0xf5, 0x83, 0xe4, 0xf0, 0xa3,
0xf0, 0x30, 0x05, 0x07, 0xe5, 0x16, 0x04, 0xf8, 0x74, 0x05, 0xf2, 0xc3, 0xe5, 0x44, 0x94, 0x40,
0xe5, 0x43, 0x94, 0x02, 0x50, 0x0c, 0xe5, 0x44, 0x94, 0x80, 0xe5, 0x43, 0x94, 0x01, 0x40, 0x02,
0xd2, 0x03, 0xe5, 0x16, 0x04, 0xf8, 0xe2, 0xc3, 0x94, 0x05, 0x40, 0x03, 0x02, 0x2d, 0x63, 0xe5,
0x17, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0x02, 0x2d, 0x63, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62,
0xc3, 0xe5, 0x44, 0x9f, 0xff, 0xe5, 0x43, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0xc0, 0x06, 0xc0, 0x07,
0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, 0x12, 0x3a, 0x34, 0x12, 0x00, 0x12, 0xd0, 0xe0, 0x2f,
0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xe5, 0x16, 0x24, 0x0b, 0x12, 0x1c, 0x34, 0xe5, 0x16, 0x24, 0x0c,
0xf9, 0xd3, 0xe3, 0x94, 0x64, 0x19, 0xe3, 0x94, 0x00, 0x40, 0x06, 0x90, 0x04, 0x57, 0x74, 0x14,
0xf0, 0x12, 0x39, 0x94, 0xf5, 0x83, 0x12, 0x3a, 0x3e, 0x24, 0x19, 0x12, 0x17, 0x42, 0xaf, 0x42,
0xae, 0x41, 0x91, 0x47, 0x8e, 0x33, 0x8f, 0x34, 0x12, 0x39, 0x7d, 0x12, 0x3a, 0x3e, 0x24, 0x1b,
0x12, 0x17, 0x42, 0xaf, 0x44, 0xae, 0x43, 0x91, 0x47, 0x8e, 0x35, 0x8f, 0x36, 0x12, 0x39, 0x69,
0x12, 0x3a, 0x05, 0xe5, 0x16, 0x24, 0x0d, 0x12, 0x16, 0x62, 0xc3, 0xe5, 0x34, 0x9f, 0xff, 0xe5,
0x33, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0x8e, 0x49, 0x8f, 0x4a, 0xe5, 0x16, 0x24, 0x0f, 0x12, 0x16,
0x62, 0xc3, 0xe5, 0x36, 0x9f, 0xff, 0xe5, 0x35, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0x8e, 0x4b, 0x8f,
0x4c, 0xd3, 0xe5, 0x4a, 0x94, 0x28, 0xe5, 0x49, 0x64, 0x80, 0x94, 0x80, 0x50, 0x0f, 0xe5, 0x4c,
0x94, 0x28, 0xe5, 0x4b, 0x64, 0x80, 0x94, 0x80, 0x50, 0x03, 0x02, 0x28, 0xad, 0xae, 0x33, 0xaf,
0x34, 0x7d, 0x04, 0x31, 0x8f, 0xac, 0x06, 0xad, 0x07, 0xe5, 0x16, 0x24, 0x0d, 0x12, 0x3a, 0x64,
0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x3a, 0x5c, 0x24, 0x0d, 0x12, 0x1c, 0x34, 0xae,
0x35, 0xaf, 0x36, 0x7c, 0x00, 0x7d, 0x04, 0x31, 0x91, 0xac, 0x06, 0xad, 0x07, 0xe5, 0x16, 0x24,
0x0f, 0x12, 0x3a, 0x64, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x3a, 0x5c, 0x24, 0x0f,
0x12, 0x1c, 0x34, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5, 0x4b, 0x64, 0x80, 0xf8, 0xe5, 0x49, 0x64,
0x80, 0x98, 0x40, 0x23, 0x75, 0x4d, 0x00, 0x75, 0x4e, 0x00, 0x75, 0x4f, 0x45, 0x75, 0x50, 0x00,
0x75, 0x51, 0x00, 0x75, 0x52, 0x47, 0xae, 0x49, 0xaf, 0x4a, 0x12, 0x2e, 0xd8, 0xe5, 0x4c, 0x24,
0x02, 0xfd, 0xe4, 0x35, 0x4b, 0x80, 0x21, 0x75, 0x4d, 0x00, 0x75, 0x4e, 0x00, 0x75, 0x4f, 0x47,
0x75, 0x50, 0x00, 0x75, 0x51, 0x00, 0x75, 0x52, 0x45, 0xae, 0x4b, 0xaf, 0x4c, 0x12, 0x2e, 0xd8,
0xe5, 0x4a, 0x24, 0x02, 0xfd, 0xe4, 0x35, 0x49, 0xfc, 0x12, 0x01, 0x84, 0x8e, 0x37, 0x8f, 0x38,
0xc3, 0xe5, 0x38, 0x94, 0x14, 0xe5, 0x37, 0x94, 0x00, 0x50, 0x08, 0x75, 0x37, 0x00, 0x75, 0x38,
0x14, 0x80, 0x11, 0xd3, 0xe5, 0x38, 0x94, 0xbe, 0xe5, 0x37, 0x94, 0x00, 0x40, 0x06, 0x75, 0x37,
0x00, 0x75, 0x38, 0xbe, 0xe5, 0x38, 0x24, 0xc8, 0xff, 0xe4, 0x35, 0x37, 0xab, 0x50, 0xaa, 0x51,
0xa9, 0x52, 0x8f, 0xf0, 0x12, 0x02, 0x88, 0xc3, 0x74, 0xc8, 0x95, 0x38, 0xff, 0xe4, 0x95, 0x37,
0xab, 0x4d, 0xaa, 0x4e, 0xa9, 0x4f, 0x8f, 0xf0, 0x12, 0x02, 0x88, 0xe5, 0x16, 0x24, 0x04, 0xf9,
0xe3, 0x70, 0x02, 0x19, 0xe3, 0x70, 0x0f, 0xe5, 0x16, 0x24, 0x06, 0xf9, 0xe3, 0x70, 0x02, 0x19,
0xe3, 0x70, 0x03, 0xf1, 0xbe, 0xf2, 0xe5, 0x16, 0x24, 0x03, 0x12, 0x16, 0x62, 0xd1, 0xd8, 0xe5,
0x46, 0x2f, 0xff, 0xe5, 0x45, 0x3e, 0xfe, 0x0d, 0x12, 0x01, 0x84, 0x8e, 0x45, 0x8f, 0x46, 0xe5,
0x16, 0x24, 0x05, 0x12, 0x16, 0x62, 0xd1, 0xd8, 0xe5, 0x48, 0x2f, 0xff, 0xe5, 0x47, 0x3e, 0xfe,
0x0d, 0x12, 0x01, 0x84, 0x8e, 0x47, 0x8f, 0x48, 0xf1, 0xbe, 0xf2, 0x80, 0x28, 0xe5, 0x16, 0x24,
0x03, 0x12, 0x16, 0x62, 0x4e, 0x60, 0x02, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0xfa, 0x8e, 0x45, 0x8f,
0x46, 0xe5, 0x16, 0x24, 0x05, 0x12, 0x16, 0x62, 0x4e, 0x60, 0x02, 0x80, 0x04, 0x7e, 0x00, 0x7f,
0xfa, 0x8e, 0x47, 0x8f, 0x48, 0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, 0xc3, 0xe5, 0x34, 0x9f,
0xf5, 0x4a, 0xe5, 0x33, 0x9e, 0xf5, 0x49, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, 0xc3, 0xe5,
0x36, 0x9f, 0xf5, 0x4c, 0xe5, 0x35, 0x9e, 0xf5, 0x4b, 0xa8, 0x16, 0xe2, 0x60, 0x02, 0x21, 0xaf,
0xf5, 0x41, 0x75, 0x42, 0x19, 0xe5, 0x17, 0x24, 0x04, 0xf9, 0xc3, 0xe3, 0x94, 0xe0, 0x19, 0xe3,
0x94, 0x01, 0x50, 0x07, 0x90, 0x03, 0x32, 0xe0, 0xff, 0x80, 0x05, 0x90, 0x03, 0x33, 0xe0, 0xff,
0x75, 0x37, 0x00, 0x8f, 0x38, 0x05, 0x38, 0xe5, 0x38, 0x70, 0x02, 0x05, 0x37, 0xe5, 0x16, 0x24,
0x13, 0x12, 0x16, 0x62, 0xc3, 0x94, 0xc0, 0xee, 0x94, 0x00, 0x40, 0x09, 0xd3, 0xef, 0x94, 0x00,
0xee, 0x94, 0x03, 0x40, 0x0b, 0x74, 0x0f, 0x25, 0x42, 0xf5, 0x42, 0xe4, 0x35, 0x41, 0xf5, 0x41,
0xac, 0x37, 0xad, 0x38, 0xae, 0x41, 0xaf, 0x42, 0x12, 0x01, 0x72, 0x12, 0x01, 0x72, 0x7c, 0x00,
0x7d, 0x23, 0x12, 0x01, 0x84, 0xef, 0x25, 0x42, 0xf5, 0x42, 0xee, 0x35, 0x41, 0xf5, 0x41, 0xd1,
0xfe, 0xaa, 0x06, 0xab, 0x07, 0xae, 0x41, 0xaf, 0x42, 0x12, 0x17, 0x7a, 0x12, 0x3a, 0x34, 0xd3,
0xeb, 0x9f, 0xea, 0x9e, 0x50, 0x0b, 0xf1, 0x05, 0xd3, 0xef, 0x95, 0x42, 0xee, 0x95, 0x41, 0x40,
0x1e, 0xe5, 0x13, 0x70, 0x1a, 0xa8, 0x16, 0x04, 0xf2, 0x7d, 0x03, 0xf1, 0x63, 0xe5, 0x16, 0x24,
0x07, 0x12, 0x1c, 0x34, 0x7d, 0x03, 0xf1, 0x5a, 0xe5, 0x16, 0x24, 0x09, 0x12, 0x1c, 0x34, 0xe5,
0x16, 0x24, 0x0b, 0x12, 0x16, 0x62, 0x7c, 0x00, 0x7d, 0x14, 0x12, 0x01, 0x84, 0x7c, 0x00, 0x7d,
0x28, 0x12, 0x01, 0x72, 0xef, 0x24, 0x0a, 0xf5, 0x42, 0xe4, 0x3e, 0xf5, 0x41, 0xf5, 0x43, 0x85,
0x42, 0x44, 0xd3, 0xe5, 0x42, 0x95, 0x4c, 0xe5, 0x41, 0x95, 0x4b, 0x40, 0x0b, 0xae, 0x4b, 0xaf,
0x4c, 0x7d, 0x02, 0x12, 0x01, 0xd9, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xc3, 0xe5, 0x42, 0x9f,
0xf5, 0x42, 0xe5, 0x41, 0x9e, 0xf5, 0x41, 0xd3, 0xe5, 0x44, 0x95, 0x4a, 0xe5, 0x43, 0x95, 0x49,
0x40, 0x06, 0x7d, 0x02, 0xf1, 0x63, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xc3, 0xe5, 0x44, 0x9f,
0xf5, 0x44, 0xe5, 0x43, 0x9e, 0xf5, 0x43, 0xf1, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xd1, 0xfe, 0xd0,
0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0x7c, 0x00, 0x7d, 0x1e, 0x12, 0x01, 0xd9, 0x8e, 0x33,
0x8f, 0x34, 0xd3, 0xe5, 0x34, 0x94, 0x0a, 0xf1, 0x11, 0x40, 0x06, 0x75, 0x33, 0x00, 0x75, 0x34,
0x0a, 0xae, 0x33, 0xaf, 0x34, 0x7c, 0x00, 0x7d, 0x04, 0x12, 0x01, 0xd9, 0xc3, 0xe5, 0x34, 0x9f,
0xf5, 0x36, 0xe5, 0x33, 0x9e, 0xf5, 0x35, 0xd3, 0xe5, 0x4a, 0x94, 0x00, 0xe5, 0x49, 0x64, 0x80,
0x94, 0x80, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x02, 0x80, 0x04, 0x7e, 0xff, 0x7f, 0xfe, 0xef, 0x25,
0x4a, 0xf5, 0x4a, 0xee, 0x35, 0x49, 0xf5, 0x49, 0xd3, 0xe5, 0x4c, 0x94, 0x00, 0xe5, 0x4b, 0x64,
0x80, 0x94, 0x80, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x02, 0x80, 0x04, 0x7e, 0xff, 0x7f, 0xfe, 0xef,
0x25, 0x4c, 0xf5, 0x4c, 0xee, 0x35, 0x4b, 0xf5, 0x4b, 0xc3, 0x74, 0x0a, 0xf1, 0x4a, 0xe5, 0x16,
0x24, 0x07, 0x12, 0x17, 0x42, 0x12, 0x01, 0x72, 0xc3, 0x74, 0x0c, 0xf1, 0x52, 0x12, 0x01, 0xd9,
0xaa, 0x06, 0xab, 0x07, 0xae, 0x49, 0xaf, 0x4a, 0x12, 0x3a, 0x46, 0xeb, 0x2f, 0xfb, 0xea, 0x3e,
0xfa, 0xc3, 0x74, 0x0d, 0xf1, 0x52, 0xae, 0x49, 0xaf, 0x4a, 0x12, 0x01, 0xd9, 0xef, 0x2b, 0xf5,
0x34, 0xee, 0x3a, 0xf5, 0x33, 0xc3, 0x74, 0x0a, 0xf1, 0x42, 0xe5, 0x16, 0x24, 0x09, 0x12, 0x17,
0x42, 0x12, 0x01, 0x72, 0xf1, 0x6c, 0x12, 0x01, 0xd9, 0xaa, 0x06, 0xab, 0x07, 0x7d, 0x04, 0xf1,
0x5a, 0xeb, 0x2f, 0xfb, 0xea, 0x3e, 0xfa, 0xf1, 0x6c, 0xae, 0x4b, 0xaf, 0x4c, 0x12, 0x01, 0xd9,
0xef, 0x2b, 0xf5, 0x36, 0xee, 0x3a, 0xf5, 0x35, 0xf1, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xd1, 0xfe,
0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x36, 0xae, 0x35,
0x12, 0x00, 0x12, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x3a, 0x55, 0xd0, 0xe0, 0x2f, 0xfd, 0xd0, 0xe0,
0x3e, 0xfc, 0xd0, 0x07, 0xd0, 0x06, 0xd3, 0xed, 0x9f, 0xee, 0x64, 0x80, 0xf8, 0xec, 0x64, 0x80,
0x98, 0x40, 0x16, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x35, 0xf5, 0x36, 0xe5, 0x16, 0x24, 0x07,
0xf1, 0xb6, 0x24, 0x09, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xe5, 0x16, 0x24, 0x19, 0xf8, 0xe2, 0xfe,
0x08, 0xe2, 0xf1, 0x18, 0xf5, 0x35, 0xd3, 0xe5, 0x48, 0x95, 0x46, 0xe5, 0x47, 0x95, 0x45, 0x40,
0x34, 0xf1, 0x83, 0x40, 0x19, 0xe5, 0x34, 0x24, 0x3e, 0xff, 0xe5, 0x33, 0x34, 0xfe, 0xfe, 0x12,
0x17, 0x73, 0xef, 0x25, 0x34, 0xf5, 0x34, 0xee, 0x35, 0x33, 0xf5, 0x33, 0x80, 0x17, 0xf1, 0x0c,
0x50, 0x13, 0xc3, 0x74, 0x1e, 0xf1, 0x4a, 0x12, 0x17, 0x73, 0xc3, 0xe5, 0x34, 0x9f, 0xf5, 0x34,
0xe5, 0x33, 0x9e, 0xf5, 0x33, 0xd3, 0xe5, 0x46, 0x95, 0x48, 0xe5, 0x45, 0x95, 0x47, 0x40, 0x3e,
0xd3, 0xe5, 0x36, 0x94, 0xa2, 0xe5, 0x35, 0x64, 0x80, 0x94, 0x83, 0x40, 0x14, 0xe5, 0x36, 0x24,
0x5e, 0xff, 0xe5, 0x35, 0x34, 0xfc, 0xfe, 0x12, 0x17, 0x73, 0xef, 0xf1, 0x2a, 0xf5, 0x35, 0x80,
0x1d, 0xc3, 0xe5, 0x36, 0x94, 0x1e, 0x12, 0x17, 0xa1, 0x50, 0x13, 0xc3, 0x74, 0x1e, 0xf1, 0x42,
0x12, 0x17, 0x73, 0xc3, 0xe5, 0x36, 0x9f, 0xf5, 0x36, 0xe5, 0x35, 0x9e, 0xf5, 0x35, 0xf1, 0xd6,
0xf1, 0x0c, 0x40, 0x04, 0xf1, 0x83, 0x40, 0x02, 0xc2, 0x02, 0x30, 0x05, 0x0c, 0x75, 0x45, 0x00,
0x75, 0x46, 0x80, 0x75, 0x47, 0x00, 0x75, 0x48, 0x80, 0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62,
0xac, 0x45, 0xad, 0x46, 0x12, 0x04, 0xb2, 0x8f, 0x3c, 0x8e, 0x3b, 0x8d, 0x3a, 0x8c, 0x39, 0xe5,
0x42, 0x25, 0x46, 0xf5, 0x46, 0xe5, 0x41, 0x35, 0x45, 0xf5, 0x45, 0xae, 0x33, 0xaf, 0x34, 0xab,
0x07, 0xaa, 0x06, 0xae, 0x41, 0xaf, 0x42, 0xf1, 0x9d, 0x25, 0x3c, 0xff, 0xee, 0x35, 0x3b, 0xfe,
0xed, 0x35, 0x3a, 0xfd, 0xec, 0x35, 0x39, 0xfc, 0xe5, 0x45, 0xf1, 0x77, 0xe5, 0x46, 0x13, 0xff,
0xe4, 0xfc, 0xfd, 0x12, 0x02, 0xd4, 0xc0, 0x06, 0xc0, 0x07, 0xae, 0x45, 0xaf, 0x46, 0x12, 0x24,
0x36, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x03, 0x6c, 0x8f, 0x3c, 0x8e, 0x3b, 0x8d, 0x3a, 0x8c, 0x39,
0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, 0xac, 0x47, 0xad, 0x48, 0x12, 0x04, 0xb2, 0x8f, 0x40,
0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x44, 0x25, 0x48, 0xf5, 0x48, 0xe5, 0x43, 0x35, 0x47,
0xf5, 0x47, 0xae, 0x35, 0xaf, 0x36, 0xab, 0x07, 0xaa, 0x06, 0xae, 0x43, 0xaf, 0x44, 0xf1, 0x9d,
0x25, 0x40, 0xff, 0xee, 0x35, 0x3f, 0xfe, 0xed, 0x35, 0x3e, 0xfd, 0xec, 0x35, 0x3d, 0xfc, 0xe5,
0x47, 0xf1, 0x77, 0xe5, 0x48, 0x13, 0xff, 0xe4, 0xfc, 0xfd, 0x12, 0x02, 0xd4, 0xc0, 0x06, 0xc0,
0x07, 0xae, 0x47, 0xaf, 0x48, 0x12, 0x24, 0x36, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x03, 0x6c, 0x8f,
0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xa8, 0x16, 0xe2, 0x64, 0x01, 0x70, 0x6b, 0xe8, 0x24,
0x19, 0x12, 0x17, 0x42, 0xc3, 0xe5, 0x3c, 0x9d, 0xff, 0xe5, 0x3b, 0x9c, 0xfe, 0xd1, 0xf2, 0x12,
0x0c, 0xea, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x17, 0x42, 0xc3, 0xe5, 0x40, 0x9d, 0xff, 0xe5, 0x3f,
0x9c, 0xfe, 0xd1, 0xe6, 0x12, 0x0c, 0xea, 0xe5, 0x16, 0x24, 0x07, 0x12, 0x16, 0x62, 0xd1, 0xd8,
0xd1, 0xf2, 0x12, 0x0d, 0x30, 0xf1, 0x8f, 0x24, 0x07, 0x12, 0x1c, 0x34, 0xe5, 0x16, 0x24, 0x09,
0x12, 0x16, 0x62, 0xd1, 0xd8, 0xd1, 0xe6, 0x12, 0x0d, 0x30, 0xf1, 0x8f, 0x24, 0x09, 0x12, 0x1c,
0x34, 0xe5, 0x17, 0x04, 0xf8, 0xe5, 0x3b, 0xf2, 0xe5, 0x3c, 0xf1, 0x32, 0xe5, 0x3f, 0xf2, 0x08,
0xe5, 0x40, 0xf2, 0xd2, 0x04, 0xc2, 0x03, 0x80, 0x1a, 0xe5, 0x16, 0xf1, 0xab, 0x24, 0x11, 0x12,
0x16, 0x62, 0x12, 0x1c, 0x31, 0xe5, 0x16, 0x24, 0x13, 0x12, 0x16, 0x62, 0xe5, 0x17, 0x24, 0x03,
0x12, 0x1c, 0x34, 0x12, 0x1d, 0xcb, 0x60, 0x05, 0xf1, 0x3a, 0xf2, 0x80, 0x54, 0xe5, 0x16, 0x24,
0x02, 0xf8, 0xe4, 0xf2, 0x80, 0x4b, 0xd1, 0xdf, 0x70, 0x23, 0xe5, 0x16, 0x04, 0xf8, 0xe2, 0xd3,
0x94, 0x03, 0x50, 0x06, 0xe5, 0x11, 0x64, 0x02, 0x70, 0x13, 0xe4, 0xf2, 0xf1, 0x3a, 0xf2, 0xe5,
0x16, 0x24, 0x19, 0xf9, 0xe5, 0x17, 0x04, 0x12, 0x1e, 0xe1, 0x12, 0x1e, 0xd8, 0xd1, 0xdf, 0x60,
0x02, 0x14, 0xf2, 0xe2, 0x70, 0x1b, 0xe5, 0x16, 0x04, 0xf8, 0xe4, 0xf2, 0xa8, 0x16, 0xf2, 0xe8,
0x24, 0x0b, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0x05, 0x11, 0x12, 0x39, 0x7d, 0x74, 0xff, 0xf0, 0xa3,
0xf0, 0xe5, 0x11, 0xb4, 0x02, 0x09, 0xd2, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x04, 0x57, 0xf0, 0x12,
0x1d, 0xcb, 0x60, 0x10, 0xe5, 0x16, 0x24, 0x1d, 0xf8, 0xe2, 0x7f, 0x01, 0x60, 0x02, 0x7f, 0x03,
0x8f, 0x53, 0xc1, 0x70, 0xe5, 0x16, 0x24, 0x1d, 0xf8, 0xe2, 0x70, 0x02, 0xc1, 0x6d, 0xd1, 0xdf,
0x60, 0x76, 0x75, 0x53, 0x03, 0x12, 0x1e, 0xd8, 0x30, 0x01, 0x08, 0xd1, 0xf2, 0x12, 0x17, 0x6c,
0xff, 0x80, 0x0d, 0xd1, 0xf2, 0x12, 0x17, 0x6c, 0xff, 0x12, 0x21, 0x94, 0x1d, 0x12, 0x01, 0xd9,
0x8e, 0x33, 0x8f, 0x34, 0x30, 0x01, 0x08, 0xd1, 0xe6, 0x12, 0x17, 0x6c, 0xff, 0x80, 0x0d, 0xd1,
0xe6, 0x12, 0x17, 0x6c, 0xff, 0x12, 0x21, 0x94, 0x1d, 0x12, 0x01, 0xd9, 0x8e, 0x35, 0x8f, 0x36,
0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, 0xc3, 0x94, 0x0a, 0xee, 0x94, 0x00, 0x40, 0x09, 0xd3,
0xef, 0x94, 0xd6, 0xee, 0x94, 0x01, 0x40, 0x05, 0xe4, 0xf5, 0x35, 0xf5, 0x36, 0xef, 0xf1, 0x18,
0xf5, 0x35, 0xf1, 0xd6, 0xe5, 0x17, 0x04, 0xf8, 0xe5, 0x33, 0xf2, 0xe5, 0x34, 0xf1, 0x32, 0xe5,
0x35, 0xf2, 0x08, 0xe5, 0x36, 0xf2, 0x80, 0x08, 0x75, 0x53, 0x02, 0x80, 0x03, 0xe4, 0xf5, 0x53,
0xe5, 0x17, 0x24, 0x06, 0xf8, 0xe5, 0x53, 0xf2, 0x64, 0x02, 0x70, 0x18, 0xe5, 0x16, 0x24, 0x19,
0x12, 0x16, 0x62, 0x12, 0x1c, 0x31, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, 0xe5, 0x17, 0x24,
0x03, 0x12, 0x1c, 0x34, 0xe5, 0x17, 0x04, 0xf9, 0xe5, 0x16, 0x24, 0x19, 0x12, 0x1e, 0xe1, 0xd1,
0xdf, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0x01, 0xe5, 0x16, 0x24, 0x1d, 0xf8, 0xef, 0xf2, 0xe5, 0x17,
0x04, 0x12, 0x16, 0x62, 0xe5, 0x16, 0x24, 0x15, 0x12, 0x1c, 0x34, 0xe5, 0x17, 0x24, 0x03, 0x12,
0x16, 0x62, 0xe5, 0x16, 0x24, 0x17, 0x12, 0x1c, 0x34, 0x05, 0x32, 0x74, 0x1f, 0x25, 0x16, 0xf5,
0x16, 0x12, 0x1c, 0x1b, 0x02, 0x24, 0x99, 0x22, 0x7c, 0x00, 0x7d, 0x0a, 0x02, 0x01, 0x72, 0xe5,
0x16, 0x24, 0x02, 0xf8, 0xe2, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x4d, 0xf5, 0x82, 0xe4, 0x34,
0x04, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x49, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0x22, 0xaf, 0x4a,
0xae, 0x49, 0x02, 0x00, 0x12, 0xaf, 0x4c, 0xae, 0x4b, 0x02, 0x00, 0x12, 0xc3, 0xe5, 0x34, 0x94,
0x1e, 0xe5, 0x33, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0x34, 0xf5, 0x34, 0xee, 0x35, 0x33, 0xf5,
0x33, 0xe5, 0x16, 0x24, 0x1b, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0x25, 0x36, 0xf5, 0x36, 0xee, 0x35,
0x35, 0x22, 0x08, 0xf2, 0xe5, 0x17, 0x24, 0x03, 0xf8, 0x22, 0xe5, 0x16, 0x24, 0x02, 0xf8, 0x74,
0x02, 0x22, 0x95, 0x36, 0xff, 0xe4, 0x95, 0x35, 0xfe, 0x22, 0x95, 0x34, 0xff, 0xe4, 0x95, 0x33,
0xfe, 0x22, 0x95, 0x34, 0xfd, 0xe4, 0x95, 0x33, 0xfc, 0x22, 0xae, 0x4b, 0xaf, 0x4c, 0x7c, 0x00,
0x02, 0x01, 0xd9, 0xae, 0x49, 0xaf, 0x4a, 0x7c, 0x00, 0x02, 0x01, 0xd9, 0xc3, 0x74, 0x0c, 0x95,
0x36, 0xfd, 0xe4, 0x95, 0x35, 0xfc, 0x22, 0xa8, 0x04, 0xa9, 0x05, 0xaa, 0x06, 0xab, 0x07, 0xc3,
0x13, 0xfe, 0x22, 0xd3, 0xe5, 0x34, 0x94, 0xc2, 0xe5, 0x33, 0x64, 0x80, 0x94, 0x81, 0x22, 0x2f,
0xff, 0xec, 0x3e, 0xfe, 0x7c, 0x00, 0x0d, 0x12, 0x01, 0xd9, 0xe5, 0x16, 0x22, 0xea, 0x33, 0x95,
0xe0, 0xf9, 0xf8, 0xe4, 0xfc, 0xfd, 0x12, 0x02, 0xe1, 0xef, 0x22, 0x24, 0x07, 0xf8, 0xe4, 0xf2,
0x08, 0xf2, 0xe5, 0x16, 0x24, 0x09, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xe5, 0x16, 0x22, 0xe5, 0x16,
0x24, 0x03, 0xf8, 0xe5, 0x45, 0xf2, 0x08, 0xe5, 0x46, 0xf2, 0xe5, 0x16, 0x24, 0x05, 0xf8, 0xe5,
0x47, 0xf2, 0x08, 0xe5, 0x48, 0x22, 0x7b, 0xdf, 0x7a, 0x01, 0xe4, 0xfd, 0xaf, 0x34, 0xae, 0x33,
0x12, 0x16, 0xbd, 0x8e, 0x33, 0x8f, 0x34, 0x7b, 0xbf, 0x7a, 0x03, 0xaf, 0x36, 0xae, 0x35, 0x12,
0x16, 0xbd, 0x8e, 0x35, 0x8f, 0x36, 0x22, 0x00, 0x12, 0x30, 0x21, 0xe4, 0x78, 0x99, 0xf6, 0x12,
0x0d, 0xc0, 0x80, 0xf7, 0x75, 0x88, 0x08, 0x75, 0x89, 0x80, 0xe5, 0x61, 0x75, 0xf0, 0x20, 0xa4,
0xff, 0xe5, 0xf0, 0x44, 0x80, 0xf5, 0x8f, 0x8f, 0x8e, 0xe4, 0x78, 0x99, 0xf6, 0x75, 0x88, 0xa0,
0x22, 0xc2, 0xaf, 0xe4, 0xf5, 0x22, 0x90, 0xff, 0x00, 0x74, 0x02, 0xf0, 0x90, 0xff, 0x03, 0x74,
0x35, 0xf0, 0x90, 0xff, 0x07, 0xe0, 0xf5, 0x23, 0x90, 0xff, 0x03, 0x74, 0x30, 0xf0, 0x75, 0x24,
0x55, 0x90, 0xff, 0x07, 0xe0, 0xf5, 0x25, 0x25, 0x24, 0xf5, 0x24, 0x74, 0x84, 0x25, 0x22, 0xf8,
0x74, 0x80, 0xf2, 0xe5, 0x23, 0xb4, 0xac, 0x15, 0xe5, 0x25, 0xd3, 0x94, 0x6e, 0x40, 0x0e, 0xe5,
0x25, 0x94, 0x96, 0x50, 0x08, 0x74, 0x84, 0x25, 0x22, 0xf8, 0xe5, 0x25, 0xf2, 0x90, 0xff, 0x03,
0xe0, 0x04, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x04, 0x40, 0xc5, 0x90, 0xff, 0x07, 0xe0,
0x65, 0x24, 0x60, 0x0b, 0x78, 0x84, 0x74, 0x80, 0xf2, 0x08, 0xf2, 0x08, 0xf2, 0x08, 0xf2, 0xe4,
0x90, 0xff, 0x00, 0xf0, 0x90, 0xff, 0x88, 0x74, 0x40, 0xf0, 0x74, 0xc0, 0xf0, 0x90, 0xff, 0x01,
0x74, 0x0f, 0xf0, 0x74, 0x0d, 0xf0, 0x43, 0x95, 0x60, 0xe4, 0xf5, 0x96, 0x75, 0x61, 0x0b, 0x11,
0x04, 0x11, 0xbf, 0xe4, 0xf5, 0x60, 0xc2, 0x05, 0xf5, 0x63, 0xf5, 0x62, 0xd2, 0xaf, 0x22, 0xe4,
0x90, 0x03, 0x34, 0xf0, 0x75, 0x58, 0xff, 0xf5, 0x57, 0xf5, 0x56, 0x90, 0x04, 0x35, 0xf0, 0xc2,
0x07, 0xc2, 0x08, 0x90, 0xff, 0x85, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x14, 0x74, 0x04, 0x31, 0x77,
0xc2, 0xaf, 0x7d, 0x03, 0x7f, 0x12, 0x12, 0x08, 0xb7, 0xd2, 0xaf, 0x90, 0xff, 0x12, 0xe0, 0x54,
0xe7, 0xf0, 0x90, 0xff, 0x11, 0xe0, 0x44, 0x18, 0xf0, 0x90, 0xff, 0x10, 0xe0, 0x54, 0xe7, 0xf0,
0x90, 0xff, 0x14, 0xe0, 0x44, 0x18, 0xf0, 0x90, 0xff, 0x1b, 0xe0, 0x44, 0x18, 0xf0, 0xe4, 0xf5,
0xa3, 0x75, 0xa1, 0x95, 0x75, 0xa2, 0x81, 0x43, 0x90, 0x10, 0x90, 0xff, 0x83, 0xe0, 0x54, 0xcf,
0xf0, 0x7e, 0x01, 0x7f, 0x00, 0x7d, 0x00, 0x7b, 0x01, 0x7a, 0x03, 0x79, 0x35, 0x12, 0x04, 0xdf,
0x90, 0x3b, 0xfc, 0xe4, 0x93, 0x90, 0x03, 0xdb, 0xf0, 0x90, 0x3b, 0xfd, 0xe4, 0x93, 0x90, 0x03,
0xdc, 0xf0, 0x90, 0x3b, 0xfb, 0xe4, 0x93, 0x90, 0x03, 0xdd, 0xf0, 0x90, 0x3b, 0xfa, 0xe4, 0x93,
0x90, 0x03, 0xde, 0xf0, 0x90, 0x3b, 0xf8, 0xe4, 0x93, 0x90, 0x03, 0xdf, 0xf0, 0x90, 0x3b, 0xf9,
0xe4, 0x93, 0x90, 0x03, 0xe0, 0xf0, 0x90, 0x3b, 0xfe, 0xe4, 0x93, 0x90, 0x03, 0xe1, 0xf0, 0x90,
0x3b, 0xff, 0xe4, 0x93, 0x90, 0x03, 0xe2, 0xf0, 0x90, 0xff, 0x18, 0xe0, 0x44, 0x04, 0xf0, 0x22,
0x8f, 0x23, 0x8d, 0x24, 0x31, 0x78, 0xe5, 0x63, 0x60, 0x0f, 0xe5, 0x24, 0xd3, 0x94, 0x17, 0x50,
0x54, 0x78, 0x9a, 0xe6, 0x44, 0x08, 0xf6, 0x80, 0x42, 0xe5, 0x56, 0x60, 0x43, 0x30, 0x07, 0x0e,
0x90, 0x04, 0x35, 0xe0, 0xc3, 0x94, 0x0f, 0x50, 0x0d, 0xe0, 0x04, 0xf0, 0x80, 0x08, 0x90, 0x04,
0x35, 0xe0, 0x60, 0x02, 0x14, 0xf0, 0xe5, 0x56, 0xb4, 0x01, 0x12, 0x90, 0x04, 0x35, 0xe0, 0x64,
0x0f, 0x70, 0x22, 0x91, 0x85, 0x74, 0xc0, 0xf0, 0x75, 0x56, 0x02, 0x80, 0x0e, 0x90, 0x04, 0x35,
0xe0, 0x70, 0x12, 0x91, 0x85, 0x74, 0xe0, 0xf0, 0x75, 0x56, 0x01, 0x75, 0x58, 0x01, 0x80, 0x05,
0xe4, 0x90, 0x04, 0x35, 0xf0, 0x91, 0x8d, 0xe5, 0x25, 0xc3, 0x94, 0x02, 0x50, 0x38, 0x91, 0x4d,
0x91, 0x5c, 0x60, 0x2e, 0x12, 0x02, 0x25, 0x7c, 0x01, 0x7d, 0xe0, 0x91, 0x7d, 0x7b, 0xe0, 0x7a,
0x01, 0x91, 0x48, 0xee, 0x8f, 0xf0, 0x12, 0x02, 0x88, 0x91, 0x4d, 0x91, 0x62, 0x7c, 0x03, 0x7d,
0x20, 0x91, 0x7d, 0x7b, 0xc0, 0x7a, 0x03, 0x91, 0x48, 0x90, 0x00, 0x02, 0xee, 0x8f, 0xf0, 0x12,
0x02, 0xa7, 0x91, 0x98, 0x80, 0xc1, 0xe5, 0x57, 0x60, 0x02, 0x61, 0xe3, 0x30, 0x08, 0x02, 0x81,
0x37, 0xe5, 0x56, 0x70, 0x04, 0x90, 0x03, 0x36, 0xf0, 0xe5, 0x58, 0x20, 0xe0, 0x02, 0x41, 0xd9,
0x78, 0x9a, 0xe6, 0xff, 0x70, 0x08, 0x90, 0x03, 0x34, 0xe0, 0x70, 0x02, 0x41, 0xd9, 0xe4, 0x90,
0x03, 0x37, 0xf0, 0xa3, 0xf0, 0xef, 0x54, 0x07, 0x60, 0x08, 0x90, 0x03, 0x37, 0x74, 0x01, 0xf0,
0x80, 0x06, 0x90, 0x03, 0x38, 0x74, 0x40, 0xf0, 0x90, 0x03, 0x34, 0xe0, 0x78, 0x9a, 0x46, 0xf5,
0x2b, 0x30, 0xe0, 0x0d, 0x90, 0x03, 0x38, 0xe0, 0x44, 0x01, 0xf0, 0xa3, 0x74, 0x90, 0xf0, 0x80,
0x33, 0xe5, 0x2b, 0x30, 0xe1, 0x0b, 0x90, 0x03, 0x38, 0xe0, 0xf0, 0xa3, 0x74, 0xf0, 0xf0, 0x80,
0x23, 0xe5, 0x2b, 0x30, 0xe2, 0x0b, 0x90, 0x03, 0x38, 0xe0, 0xf0, 0xa3, 0x74, 0x50, 0xf0, 0x80,
0x13, 0xe5, 0x2b, 0x30, 0xe3, 0x0e, 0xe5, 0x24, 0x90, 0x05, 0xec, 0x93, 0x90, 0x04, 0x08, 0xf0,
0xe4, 0x78, 0x9a, 0xf6, 0x90, 0x03, 0x3a, 0x74, 0x03, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x91, 0x54,
0x78, 0x9a, 0xe6, 0x90, 0x03, 0x34, 0xf0, 0x30, 0xe4, 0x02, 0xe4, 0xf0, 0x90, 0x03, 0x34, 0xe0,
0x7f, 0xff, 0x60, 0x02, 0x7f, 0x01, 0x8f, 0x58, 0x22, 0xe5, 0x58, 0x20, 0xe1, 0x02, 0x61, 0xe3,
0xe4, 0x90, 0x03, 0x37, 0xf0, 0xe5, 0x11, 0xb4, 0x02, 0x0c, 0xe5, 0x13, 0xd3, 0x94, 0x05, 0x40,
0x05, 0x75, 0x13, 0x05, 0x61, 0xaa, 0xe5, 0x13, 0x60, 0x07, 0x90, 0x04, 0x40, 0x74, 0x01, 0xf0,
0x22, 0x75, 0x26, 0x03, 0xe4, 0xf5, 0x27, 0xe5, 0x23, 0x24, 0x05, 0xf8, 0xe6, 0x70, 0x08, 0xe5,
0x23, 0x24, 0x0b, 0xf8, 0xe6, 0x60, 0x08, 0x7f, 0x20, 0x7a, 0x03, 0x79, 0x38, 0x91, 0xa6, 0x91,
0x8d, 0xe5, 0x25, 0xc3, 0x94, 0x02, 0x40, 0x02, 0x61, 0xaa, 0x91, 0x4d, 0x91, 0x5c, 0x60, 0x76,
0x90, 0x03, 0x37, 0xe0, 0x04, 0xf0, 0x74, 0x35, 0x25, 0x26, 0x91, 0x40, 0x74, 0x80, 0xf0, 0x90,
0x04, 0x40, 0x74, 0x02, 0xf0, 0x91, 0x5c, 0xff, 0xb4, 0x02, 0x0b, 0x74, 0x35, 0x25, 0x26, 0x91,
0x40, 0x74, 0x40, 0xf0, 0x80, 0x0c, 0xef, 0xb4, 0x01, 0x08, 0x74, 0x35, 0x25, 0x26, 0x91, 0x40,
0xe4, 0xf0, 0x91, 0x39, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x91, 0x4d, 0x12, 0x02, 0x25, 0xfb,
0xaa, 0xf0, 0xea, 0xff, 0xed, 0x4f, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xaf, 0x03, 0x91, 0x69, 0x91,
0x40, 0xef, 0xf0, 0xab, 0x28, 0xaa, 0x29, 0x91, 0x62, 0xe5, 0xf0, 0xff, 0xe5, 0x25, 0xc4, 0x54,
0xf0, 0x4f, 0x91, 0x68, 0x91, 0x40, 0xef, 0xf0, 0x91, 0x62, 0x91, 0x68, 0x91, 0x40, 0xef, 0x91,
0x38, 0xe4, 0x91, 0x38, 0xe4, 0xf0, 0x91, 0x98, 0x61, 0x21, 0x90, 0x04, 0x40, 0xe0, 0x60, 0x26,
0x14, 0xf0, 0x90, 0x03, 0x37, 0xe0, 0x70, 0x1c, 0xa3, 0xe0, 0xff, 0xf4, 0x60, 0x06, 0xef, 0x54,
0x0f, 0x44, 0x40, 0xf0, 0x90, 0x03, 0x3e, 0xe0, 0xff, 0xf4, 0x60, 0x06, 0xef, 0x54, 0x0f, 0x44,
0x40, 0xf0, 0x91, 0x54, 0x91, 0x54, 0x90, 0x03, 0x37, 0xe0, 0x7f, 0xff, 0x60, 0x02, 0x7f, 0x02,
0x8f, 0x58, 0x22, 0xe5, 0x57, 0x64, 0xe0, 0x70, 0x4e, 0x31, 0x78, 0xe5, 0x23, 0x24, 0x04, 0xf8,
0xe6, 0x70, 0x05, 0x78, 0x9a, 0xe6, 0x60, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x04,
0x37, 0xef, 0xf0, 0xe5, 0x23, 0x24, 0x0a, 0xf8, 0xe6, 0x60, 0x03, 0xe0, 0x04, 0xf0, 0xa8, 0x23,
0xe6, 0xff, 0x08, 0xe6, 0x90, 0x04, 0x38, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0xe5, 0x23, 0x24, 0x02,
0x91, 0x71, 0xe5, 0x23, 0x24, 0x06, 0x91, 0x71, 0xe5, 0x23, 0x24, 0x08, 0x91, 0x71, 0x78, 0x9a,
0xe6, 0x90, 0x04, 0x36, 0xf0, 0x91, 0x54, 0x22, 0xf0, 0xaf, 0x26, 0x05, 0x26, 0x74, 0x35, 0x2f,
0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83, 0x22, 0xf9, 0xf8, 0x12, 0x03, 0x6c, 0xab, 0x28, 0xaa,
0x29, 0xa9, 0x2a, 0x22, 0x90, 0xff, 0x18, 0xe0, 0x54, 0xfb, 0xf0, 0x22, 0x90, 0x00, 0x05, 0x02,
0x01, 0x33, 0x90, 0x00, 0x02, 0x02, 0x02, 0x50, 0xff, 0xae, 0x26, 0x05, 0x26, 0x74, 0x35, 0x2e,
0x22, 0xf8, 0xe6, 0xff, 0x08, 0xe6, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x22, 0xff, 0xae, 0xf0,
0x12, 0x04, 0xb2, 0xe4, 0x22, 0x78, 0x9a, 0x76, 0x10, 0x90, 0x03, 0x36, 0x22, 0xe4, 0xf5, 0x25,
0xf5, 0x28, 0xf5, 0x29, 0x85, 0x23, 0x2a, 0x22, 0x05, 0x25, 0x74, 0x06, 0x25, 0x2a, 0xf5, 0x2a,
0xe4, 0x35, 0x29, 0xf5, 0x29, 0x22, 0x7e, 0x00, 0x7d, 0xff, 0x7b, 0x01, 0x02, 0x04, 0xdf, 0xc0,
0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xaf, 0xa3, 0xef, 0x54,
0xe8, 0x60, 0x03, 0x75, 0x5c, 0x00, 0xef, 0x20, 0xe0, 0x02, 0xa1, 0xe3, 0xe5, 0x5c, 0x64, 0x02,
0x60, 0x02, 0xa1, 0x7d, 0xaf, 0xa4, 0x05, 0x5d, 0xe5, 0x5d, 0xb4, 0x01, 0x12, 0x8f, 0x5e, 0x74,
0x35, 0x2f, 0xf9, 0xe4, 0x34, 0x03, 0x75, 0x59, 0x01, 0xf5, 0x5a, 0x89, 0x5b, 0xa1, 0x78, 0x78,
0x59, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x04, 0xa2, 0xef, 0x12, 0x01, 0x60, 0xe5, 0x5d, 0x64, 0x02,
0x70, 0x76, 0xe5, 0x5e, 0x70, 0x3f, 0x8f, 0x57, 0xbf, 0x04, 0x0e, 0x75, 0x59, 0x01, 0x75, 0x5a,
0x00, 0x75, 0x5b, 0xdf, 0x75, 0x62, 0x03, 0x80, 0x5f, 0xbf, 0xe0, 0x0b, 0x75, 0x59, 0x01, 0x75,
0x5a, 0x04, 0x75, 0x5b, 0x36, 0x80, 0x51, 0xbf, 0x06, 0x0b, 0x75, 0x59, 0x01, 0x75, 0x5a, 0x01,
0x75, 0x5b, 0x61, 0x80, 0x43, 0xef, 0x64, 0x07, 0x70, 0x3e, 0x75, 0x59, 0x01, 0x75, 0x5a, 0x00,
0x75, 0x5b, 0x8b, 0x80, 0x33, 0xe5, 0x57, 0x70, 0x2f, 0xe5, 0x5e, 0xb4, 0xa5, 0x08, 0xbf, 0x03,
0x05, 0x75, 0x62, 0x02, 0x80, 0x22, 0xe5, 0x5e, 0xb4, 0xd0, 0x07, 0xef, 0x54, 0x01, 0xf5, 0x63,
0x80, 0x16, 0xe5, 0x5e, 0xb4, 0xb0, 0x11, 0xef, 0x54, 0x01, 0xf5, 0x56, 0x90, 0x03, 0x36, 0x74,
0xe0, 0xf0, 0x90, 0x04, 0x40, 0x74, 0x01, 0xf0, 0x75, 0xa3, 0x10, 0x80, 0x66, 0xe5, 0x5c, 0xb4,
0x01, 0x1f, 0xab, 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x01, 0x1a, 0xf5, 0xa4, 0x75, 0xa3, 0x04,
0xef, 0x20, 0xe1, 0x4f, 0x74, 0x01, 0x25, 0x5b, 0xf5, 0x5b, 0xe4, 0x35, 0x5a, 0xf5, 0x5a, 0x80,
0x42, 0xe5, 0x5c, 0x70, 0x3b, 0xaf, 0xa4, 0xef, 0xc3, 0x13, 0x64, 0x15, 0x70, 0x32, 0xef, 0x30,
0xe0, 0x1e, 0xe5, 0x57, 0x70, 0x0f, 0x78, 0x59, 0x75, 0xf0, 0x01, 0x12, 0x04, 0xa2, 0x12, 0x01,
0x1a, 0xf5, 0xa4, 0x80, 0x03, 0x85, 0x57, 0xa4, 0x75, 0xa3, 0x14, 0x75, 0x5c, 0x01, 0x80, 0x0c,
0x75, 0xa3, 0x10, 0x75, 0x5d, 0x00, 0x75, 0x5e, 0x00, 0x75, 0x5c, 0x02, 0x31, 0x78, 0x80, 0x03,
0x75, 0xa3, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0,
0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0x75, 0x89, 0x80, 0x78, 0x99, 0xe6, 0xc3, 0x94, 0x28,
0x50, 0x04, 0x06, 0x75, 0x8a, 0x00, 0xe5, 0x5f, 0x60, 0x02, 0x15, 0x5f, 0xd0, 0x00, 0xd0, 0xd0,
0xd0, 0xe0, 0x32, 0xc3, 0xef, 0x9b, 0xf5, 0x33, 0xee, 0x9a, 0xf5, 0x32, 0xc3, 0xed, 0x95, 0x31,
0xf5, 0x35, 0xec, 0x95, 0x30, 0xf5, 0x34, 0xaf, 0x33, 0xae, 0x32, 0x12, 0x00, 0x12, 0x8e, 0x36,
0x8f, 0x37, 0xaf, 0x35, 0xae, 0x34, 0x12, 0x00, 0x12, 0xab, 0x07, 0xaa, 0x06, 0xe5, 0x33, 0x45,
0x32, 0x60, 0x19, 0xd3, 0xe5, 0x33, 0x94, 0x00, 0xe5, 0x32, 0x64, 0x80, 0x94, 0x80, 0x40, 0x06,
0x7e, 0x00, 0x7f, 0x01, 0x80, 0x0a, 0x7e, 0xff, 0x7f, 0xff, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00,
0x8e, 0x32, 0x8f, 0x33, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x19, 0xd3, 0xe5, 0x35, 0x94, 0x00, 0xe5,
0x34, 0x64, 0x80, 0x94, 0x80, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x0a, 0x7e, 0xff, 0x7f,
0xff, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x8e, 0x34, 0x8f, 0x35, 0xd3, 0xeb, 0x95, 0x37, 0xea,
0x95, 0x36, 0xe5, 0x37, 0x40, 0x10, 0x2b, 0xff, 0xe5, 0x36, 0x3a, 0xfe, 0xe5, 0x37, 0x24, 0x01,
0xfd, 0xe4, 0x35, 0x36, 0x80, 0x0c, 0x2b, 0xff, 0xe5, 0x36, 0x3a, 0xfe, 0xeb, 0x24, 0x01, 0xfd,
0xe4, 0x3a, 0xfc, 0x12, 0x01, 0x84, 0xd3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x40, 0x15, 0xd3,
0xe5, 0x37, 0x9b, 0xe5, 0x36, 0x9a, 0x40, 0x07, 0xe4, 0xf5, 0x34, 0xf5, 0x35, 0x80, 0x05, 0xe4,
0xf5, 0x32, 0xf5, 0x33, 0xe4, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x34, 0x06,
0xf1, 0x06, 0xb5, 0x33, 0x19, 0xec, 0xb5, 0x32, 0x15, 0xef, 0x25, 0xe0, 0x24, 0x05, 0xf5, 0x82,
0xe4, 0x34, 0x06, 0xf1, 0x06, 0x65, 0x35, 0x70, 0x03, 0xec, 0x65, 0x34, 0x60, 0x04, 0x0f, 0xbf,
0x09, 0xd4, 0xef, 0x04, 0xff, 0x22, 0xf5, 0x83, 0xe4, 0x93, 0xfd, 0x33, 0x95, 0xe0, 0xfc, 0xed,
0x22, 0xa8, 0x07, 0xe6, 0xf5, 0x23, 0x08, 0xe6, 0xf5, 0x24, 0xef, 0x24, 0x02, 0xf8, 0xe6, 0xf5,
0x25, 0x08, 0xe6, 0xf5, 0x26, 0xef, 0x24, 0x0a, 0xf8, 0xe6, 0x60, 0x12, 0x12, 0x39, 0x53, 0x50,
0x07, 0x08, 0x06, 0xe6, 0x18, 0x70, 0x01, 0x06, 0x75, 0x63, 0x01, 0x02, 0x39, 0x37, 0xef, 0x24,
0x05, 0xf8, 0xe6, 0xf5, 0x29, 0xef, 0x24, 0x04, 0xf8, 0xe6, 0x70, 0x3e, 0xe5, 0x29, 0xb4, 0x02,
0x17, 0xe5, 0x63, 0xb4, 0x04, 0x03, 0x7f, 0x17, 0x22, 0xe5, 0x63, 0x64, 0x08, 0x60, 0x03, 0x02,
0x39, 0x2c, 0x75, 0x63, 0x09, 0x02, 0x39, 0x2c, 0x78, 0x73, 0xe6, 0xc3, 0x94, 0xff, 0x50, 0x01,
0x06, 0x74, 0x1e, 0xc3, 0x78, 0x73, 0x96, 0x50, 0x03, 0x75, 0x63, 0x01, 0xe5, 0x63, 0x64, 0x09,
0x60, 0x03, 0x02, 0x39, 0x2c, 0x05, 0x63, 0x02, 0x39, 0x2c, 0xe5, 0x29, 0x64, 0x01, 0x70, 0x76,
0xe5, 0x63, 0xb4, 0x03, 0x05, 0x75, 0x63, 0x04, 0x80, 0x64, 0xe5, 0x63, 0xb4, 0x09, 0x04, 0x15,
0x63, 0x80, 0x5b, 0x75, 0x63, 0x02, 0xe4, 0x78, 0x64, 0xf6, 0x08, 0xf6, 0x78, 0x6a, 0x12, 0x04,
0x7d, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x78, 0x6e, 0xf6, 0x12, 0x39, 0x46, 0x78, 0x75, 0xf6, 0x18,
0xf6, 0x78, 0x76, 0xf6, 0x78, 0x66, 0x12, 0x39, 0x47, 0xc3, 0xe5, 0x24, 0x94, 0x14, 0xe5, 0x23,
0x64, 0x80, 0x94, 0x80, 0x40, 0x25, 0xe5, 0x26, 0x94, 0x14, 0xe5, 0x25, 0x64, 0x80, 0x94, 0x80,
0x40, 0x19, 0xd3, 0xe5, 0x24, 0x94, 0xcc, 0xe5, 0x23, 0x64, 0x80, 0x94, 0x81, 0x50, 0x0c, 0xe5,
0x26, 0x94, 0xac, 0xe5, 0x25, 0x64, 0x80, 0x94, 0x83, 0x40, 0x03, 0x75, 0x63, 0x01, 0xe4, 0x78,
0x73, 0xf6, 0x78, 0x77, 0x31, 0x47, 0xe5, 0x63, 0xc3, 0x94, 0x02, 0x50, 0x02, 0x21, 0x1a, 0xe5,
0x63, 0xb4, 0x02, 0x02, 0x05, 0x63, 0xc3, 0xe5, 0x26, 0x78, 0x7a, 0x96, 0xff, 0xe5, 0x25, 0x31,
0x40, 0xc0, 0x06, 0xc0, 0x07, 0xc3, 0x78, 0x78, 0x31, 0x3a, 0xd0, 0xe0, 0x2f, 0xf5, 0x28, 0xd0,
0xe0, 0x3e, 0xf5, 0x27, 0xc3, 0xe5, 0x28, 0x94, 0x0f, 0xe5, 0x27, 0x94, 0x00, 0x50, 0x02, 0x01,
0xe3, 0x78, 0x77, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x08, 0xe6, 0xf5, 0x30, 0x08, 0xe6, 0xf5, 0x31,
0xad, 0x26, 0xac, 0x25, 0xaf, 0x24, 0xae, 0x23, 0x12, 0x36, 0x13, 0x78, 0x75, 0xe6, 0xfe, 0x6f,
0x60, 0x08, 0xe4, 0x08, 0xf6, 0x18, 0xa6, 0x07, 0x80, 0x74, 0x78, 0x76, 0xe6, 0x64, 0x02, 0x70,
0x6d, 0x78, 0x74, 0xe6, 0xfd, 0xee, 0xc3, 0x9d, 0xff, 0xe4, 0x94, 0x00, 0xfe, 0x12, 0x00, 0x12,
0xd3, 0xef, 0x94, 0x01, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x1a, 0x78, 0x74, 0xe6, 0xff, 0x08,
0xe6, 0x9f, 0xff, 0xe4, 0x94, 0x00, 0xfe, 0x12, 0x00, 0x12, 0xc3, 0xef, 0x94, 0x07, 0xee, 0x64,
0x80, 0x94, 0x80, 0x40, 0x05, 0x78, 0x74, 0xe6, 0x70, 0x30, 0x78, 0x6a, 0x12, 0x04, 0x58, 0x78,
0x04, 0x12, 0x04, 0x45, 0x78, 0x6a, 0x12, 0x04, 0x71, 0x78, 0x6a, 0x12, 0x04, 0x64, 0xc0, 0x00,
0x78, 0x75, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0xd0, 0x00, 0x12, 0x03, 0xfe, 0x78, 0x6a, 0x12,
0x04, 0x71, 0x78, 0x6e, 0x06, 0x78, 0x75, 0xe6, 0x18, 0xf6, 0xe4, 0x78, 0x76, 0xf6, 0x78, 0x76,
0x06, 0x31, 0x46, 0xc3, 0xe5, 0x26, 0x78, 0x69, 0x96, 0xff, 0xe5, 0x25, 0x31, 0x40, 0xc0, 0x06,
0xc0, 0x07, 0xc3, 0x78, 0x67, 0x31, 0x3a, 0xd0, 0xe0, 0x2f, 0xf5, 0x28, 0xd0, 0xe0, 0x3e, 0xf5,
0x27, 0xc3, 0xe5, 0x28, 0x94, 0x96, 0xe5, 0x27, 0x94, 0x00, 0x50, 0x0b, 0x78, 0x65, 0xe6, 0x94,
0x78, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x63, 0x08, 0x31, 0x53, 0x50, 0x07, 0x08, 0x06,
0xe6, 0x18, 0x70, 0x01, 0x06, 0x31, 0x5e, 0x40, 0x03, 0x75, 0x63, 0x01, 0xe5, 0x63, 0xb4, 0x0a,
0x06, 0x75, 0x63, 0x01, 0x02, 0x1e, 0xf1, 0x7f, 0xff, 0x22, 0xe5, 0x24, 0x96, 0xff, 0xe5, 0x23,
0x18, 0x96, 0xfe, 0x02, 0x00, 0x12, 0x08, 0xa6, 0x23, 0x08, 0xa6, 0x24, 0x08, 0xa6, 0x25, 0x08,
0xa6, 0x26, 0x22, 0xc3, 0x78, 0x65, 0xe6, 0x94, 0xe8, 0x18, 0xe6, 0x94, 0x03, 0x22, 0xd3, 0x78,
0x65, 0xe6, 0x94, 0xf4, 0x18, 0xe6, 0x94, 0x01, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x41, 0xf5,
0x82, 0xe4, 0x34, 0x04, 0xf5, 0x83, 0xe5, 0x41, 0xf0, 0xa3, 0xe5, 0x42, 0xf0, 0xe5, 0x32, 0x25,
0xe0, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0xf5, 0x83, 0x22, 0x7e, 0x00, 0x7d, 0x00, 0x7b,
0x00, 0x02, 0x04, 0xdf, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x41, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0x22,
0xe5, 0x32, 0x25, 0xe0, 0x24, 0x61, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0x22, 0x74, 0x3a,
0x25, 0x36, 0xf8, 0xa6, 0x37, 0xe5, 0x36, 0x25, 0xe0, 0x24, 0x87, 0xf8, 0xa6, 0x3d, 0x08, 0xa6,
0x3e, 0x05, 0x36, 0x22, 0xf9, 0x09, 0xe3, 0x25, 0xe0, 0xff, 0x19, 0xe3, 0x33, 0xfe, 0xef, 0x25,
0x3c, 0xf5, 0x3c, 0xee, 0x35, 0x3b, 0xf5, 0x3b, 0x22, 0x74, 0x51, 0x25, 0x32, 0xf5, 0x82, 0xe4,
0x34, 0x04, 0xf5, 0x83, 0x22, 0xf8, 0xe5, 0x43, 0xf2, 0x08, 0xe5, 0x44, 0xf2, 0x22, 0xf8, 0xe5,
0x41, 0xf2, 0x08, 0xe5, 0x42, 0xf2, 0x22, 0xef, 0x54, 0x07, 0x90, 0x07, 0xdd, 0x93, 0xfc, 0xef,
0xc4, 0x54, 0x0f, 0xff, 0x22, 0xe5, 0x43, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0x22, 0xaf, 0x36, 0x7c,
0x00, 0x12, 0x01, 0xd9, 0x8e, 0x35, 0x8f, 0x36, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x87, 0xf5,
0x82, 0xe4, 0x34, 0x02, 0x22, 0x7d, 0x00, 0x7b, 0xff, 0x7e, 0x00, 0x02, 0x00, 0xf4, 0xee, 0x8f,
0xf0, 0x02, 0x02, 0x0f, 0xc3, 0xe5, 0x42, 0x9f, 0xff, 0xe5, 0x41, 0x9e, 0xfe, 0x22, 0xe0, 0xfa,
0xa3, 0xe0, 0xfb, 0xe5, 0x16, 0x22, 0x7c, 0x00, 0x7d, 0x03, 0x02, 0x01, 0xd9, 0xe0, 0xfe, 0xa3,
0xe0, 0xc3, 0x95, 0x44, 0x22, 0xaf, 0x34, 0xae, 0x33, 0x02, 0x00, 0x12, 0x2d, 0xff, 0xec, 0x3e,
0xfe, 0xe5, 0x16, 0x22, 0xf9, 0xe3, 0xfe, 0x09, 0xe3, 0x78, 0x02, 0x22, 0xe5, 0x3b, 0xf0, 0xa3,
0xe5, 0x3c, 0xf0, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x01, 0x10, 0x00, 0x0b, 0x04,
};
#endif

View File

@@ -0,0 +1,984 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst8xxT_fw.h
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef HYNITRON_FIRMWARE_H
#define HYNITRON_FIRMWARE_H
static const uint8_t fw_bin[] = {
0x00, 0x00, 0x00, 0x3c, 0xdc, 0x56,
0x02, 0x2b, 0xae, 0x75, 0x91, 0xcc, 0x75, 0x91, 0x00, 0x32, 0x32, 0x22, 0x02, 0x00, 0x03, 0x02,
0x2e, 0xfe, 0x74, 0xb7, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xff, 0x22, 0x22,
0x00, 0x02, 0x32, 0x3f, 0xe4, 0x7b, 0x02, 0xfa, 0xf9, 0xf8, 0xaf, 0x00, 0xae, 0x00, 0xad, 0x00,
0xac, 0x00, 0x12, 0x0f, 0x42, 0xef, 0x25, 0x00, 0xff, 0xee, 0x35, 0x00, 0xfe, 0xed, 0x35, 0x00,
0xfd, 0xec, 0x35, 0x00, 0xfc, 0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0xa8, 0x00, 0x12, 0x0f, 0x42,
0xef, 0x24, 0xe0, 0xfb, 0xee, 0x34, 0xff, 0xfa, 0xed, 0x34, 0xff, 0xf9, 0xec, 0x34, 0xff, 0xf8,
0x85, 0x0f, 0x82, 0x85, 0x0e, 0x83, 0x22, 0x74, 0x1c, 0x93, 0x24, 0x64, 0xff, 0xe4, 0x33, 0xfe,
0xe4, 0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, 0x64, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, 0x42, 0x8f,
0x00, 0x8e, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xab, 0x00, 0xaa, 0x00, 0xa9,
0x00, 0xa8, 0x00, 0xe4, 0xfc, 0xfd, 0xc3, 0x02, 0x0f, 0xd4, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x0d,
0xf8, 0xe4, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x16, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xa8, 0x07, 0xe8,
0x24, 0x18, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xef, 0x04, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, 0xef, 0x24,
0x2b, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x04, 0x12, 0x0c, 0x68, 0x78, 0x66, 0xe6,
0xff, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0xef, 0x04, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, 0xef, 0x24, 0x07,
0x7f, 0x06, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x02, 0x0c, 0x68, 0xeb, 0x25, 0xe0, 0x25,
0xe0, 0x24, 0x61, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x22, 0xe6, 0xff, 0x24, 0x2b, 0xf8, 0xe2,
0xfc, 0x08, 0xe2, 0xfd, 0xa8, 0x07, 0xe8, 0x04, 0xf8, 0xec, 0xf2, 0x08, 0xed, 0xf2, 0x78, 0x66,
0xe6, 0xff, 0x24, 0x2d, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0xa8, 0x07, 0xe8, 0x22, 0xab, 0x00,
0xaa, 0x00, 0xa9, 0x00, 0xa8, 0x00, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xa8, 0x04,
0xa9, 0x05, 0xaa, 0x06, 0xab, 0x07, 0x22, 0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0xe5, 0x00, 0x75,
0xf0, 0x02, 0xa4, 0xf5, 0x82, 0x85, 0xf0, 0x83, 0x02, 0x0d, 0xe6, 0x74, 0x1d, 0x93, 0x24, 0x64,
0xff, 0xe4, 0x33, 0xfe, 0xe4, 0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, 0x64, 0xfa, 0xf9, 0xf8,
0x12, 0x0f, 0x42, 0x8f, 0x00, 0x8e, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xab,
0x00, 0xaa, 0x00, 0xa9, 0x00, 0xa8, 0x00, 0xe4, 0xfc, 0xfd, 0xc3, 0x02, 0x0f, 0xd4, 0xaf, 0x00,
0xef, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xfe, 0x74, 0xb5, 0x2f, 0xf5,
0x82, 0x74, 0x00, 0x3e, 0xf5, 0x83, 0x22, 0x78, 0x68, 0xa6, 0x07, 0x78, 0x6b, 0xe6, 0x78, 0x69,
0xf6, 0x90, 0x00, 0xb7, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x00, 0xb5, 0xcf, 0xf0, 0xa3, 0xef, 0xf0,
0x08, 0x76, 0xff, 0x22, 0x7e, 0x00, 0x7d, 0x00, 0x7f, 0x04, 0x7b, 0x01, 0x7a, 0x00, 0x79, 0xb5,
0x02, 0x10, 0x98, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xed, 0x39, 0xfd, 0xec, 0x38, 0xfc, 0x22,
0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0x85, 0x00, 0x82, 0x75, 0x83, 0x00, 0xe5, 0x00, 0x12, 0x0c,
0xe6, 0xe5, 0x00, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0xf5, 0x83, 0x22, 0x74,
0x15, 0x93, 0x08, 0x26, 0x25, 0xe0, 0x24, 0x5f, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0xef, 0x25,
0xe0, 0x24, 0x60, 0xf8, 0xe2, 0x2d, 0xff, 0x18, 0xe2, 0x3c, 0xc3, 0x13, 0xf5, 0x00, 0xef, 0x13,
0xf5, 0x00, 0xd3, 0x74, 0x10, 0x93, 0x95, 0x00, 0x74, 0x0f, 0x93, 0x95, 0x00, 0x22, 0xe5, 0x00,
0x25, 0xe0, 0xff, 0xe5, 0x00, 0x33, 0xfe, 0xef, 0x24, 0xff, 0xff, 0xee, 0x34, 0xff, 0xfe, 0xe4,
0xfc, 0xfd, 0x22, 0xeb, 0x7b, 0x64, 0x2f, 0xff, 0xea, 0x3e, 0xfe, 0xe9, 0x3d, 0xfd, 0xe8, 0x3c,
0xfc, 0xe4, 0xfa, 0xf9, 0xf8, 0x22, 0x74, 0x1c, 0x93, 0x24, 0x64, 0xff, 0xe4, 0x33, 0xfe, 0xe4,
0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, 0x64, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, 0x42, 0x8f, 0x00,
0x8e, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0x22, 0xe5, 0x00, 0x25, 0xe0, 0x24, 0x68, 0xf8, 0xe6, 0xff,
0x33, 0x95, 0xe0, 0xfe, 0xad, 0x00, 0xed, 0x33, 0x95, 0xe0, 0xfc, 0xc3, 0x22, 0x93, 0xfd, 0x12,
0x0d, 0x08, 0x7c, 0x00, 0x7d, 0x32, 0x12, 0x0d, 0x1a, 0xe5, 0x28, 0x2f, 0xf5, 0x2e, 0xe5, 0x27,
0x3e, 0xf5, 0x2d, 0xd3, 0xe5, 0x2e, 0x94, 0x00, 0xe5, 0x2d, 0x64, 0x80, 0x94, 0x80, 0x22, 0x7a,
0x00, 0x79, 0x02, 0x7b, 0xfe, 0x7e, 0x00, 0x7f, 0x06, 0x02, 0x0c, 0x68, 0x75, 0xf0, 0x2f, 0xa4,
0x24, 0x02, 0xf8, 0xee, 0xf2, 0x08, 0xef, 0xf2, 0x22, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x60,
0xf8, 0xe2, 0x2f, 0xf5, 0x26, 0x18, 0xe2, 0x3e, 0xf5, 0x25, 0x22, 0x13, 0x2d, 0xff, 0xee, 0x3c,
0xfe, 0x7c, 0x00, 0x7d, 0x03, 0x02, 0x0d, 0x08, 0x25, 0xe0, 0x24, 0x60, 0xf8, 0xe2, 0x2f, 0xff,
0x18, 0xe2, 0x3e, 0xfe, 0x22, 0x7e, 0x00, 0x7f, 0x04, 0x7d, 0xff, 0x7b, 0x00, 0x7a, 0x00, 0x79,
0x68, 0x02, 0x10, 0x98, 0x24, 0x09, 0xf8, 0xec, 0xf2, 0x08, 0xed, 0xf2, 0x78, 0x66, 0xe6, 0x24,
0x0e, 0xf8, 0xe2, 0xc3, 0x22, 0x74, 0x01, 0x93, 0xfe, 0x74, 0x02, 0x93, 0xff, 0xe4, 0xfc, 0xfd,
0x02, 0x10, 0x17, 0x74, 0x1a, 0x93, 0xff, 0x33, 0x95, 0xe0, 0xfe, 0xfd, 0xfc, 0xeb, 0x2f, 0x22,
0xaf, 0x00, 0xef, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xab, 0x00, 0xaa,
0x00, 0xa9, 0x00, 0x8f, 0x82, 0xf5, 0x83, 0x02, 0x0d, 0xe6, 0xae, 0x00, 0xaf, 0x00, 0xab, 0x07,
0xaa, 0x06, 0xc3, 0xe5, 0x00, 0x9b, 0xfb, 0xe5, 0x00, 0x9a, 0xfa, 0xe5, 0x00, 0x94, 0x00, 0xf9,
0xe5, 0x00, 0x94, 0x00, 0x22, 0x85, 0x0d, 0x82, 0x85, 0x0c, 0x83, 0x74, 0x04, 0x93, 0xfe, 0x74,
0x05, 0x93, 0xff, 0x22, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x07, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, 0xef,
0x22, 0xeb, 0x25, 0xe0, 0x24, 0x68, 0xf8, 0xe6, 0x22, 0xae, 0x00, 0xaf, 0x00, 0xab, 0x00, 0xaa,
0x00, 0xa9, 0x00, 0xa8, 0x00, 0x22, 0xe5, 0x00, 0x25, 0xe0, 0xff, 0xe5, 0x00, 0x33, 0xab, 0x07,
0xfa, 0xe4, 0xf9, 0xf8, 0x22, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x04, 0x02, 0x0c,
0x68, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0xc3, 0xe5, 0x00, 0x9d, 0xf5, 0x00, 0xe5, 0x00, 0x9c,
0xf5, 0x00, 0xa8, 0x07, 0xe8, 0x22, 0x2f, 0xff, 0xe0, 0x3e, 0xfe, 0xd3, 0xe5, 0x00, 0x9f, 0xe5,
0x00, 0x9e, 0x22, 0xc3, 0xe5, 0x00, 0x95, 0x00, 0xff, 0xe5, 0x00, 0x95, 0x00, 0xfe, 0x22, 0xe4,
0xfa, 0xf9, 0xf8, 0xee, 0x33, 0x95, 0xe0, 0xfd, 0xfc, 0x22, 0x74, 0x18, 0x93, 0xfb, 0x7c, 0x00,
0x7d, 0x0a, 0x12, 0x0d, 0x1a, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x10, 0x6b, 0xef, 0x22, 0xc3, 0xe5,
0x00, 0x95, 0x00, 0xff, 0xe5, 0x00, 0x95, 0x00, 0xfe, 0xe4, 0x95, 0x00, 0xfd, 0xe4, 0x95, 0x00,
0xfc, 0x22, 0xe4, 0x93, 0xfd, 0x7c, 0x00, 0x74, 0x03, 0x93, 0xfe, 0x74, 0x04, 0x93, 0xff, 0x22,
0xc3, 0x74, 0x64, 0x95, 0x23, 0xff, 0xe4, 0x94, 0x00, 0xfe, 0xe4, 0xfc, 0xfd, 0x22, 0x9d, 0xfd,
0xe4, 0x94, 0x00, 0xfc, 0xe5, 0x22, 0x75, 0xf0, 0x0a, 0xa4, 0x22, 0x25, 0xe0, 0x24, 0x5f, 0xf8,
0xe2, 0x22, 0xc3, 0xe5, 0x00, 0x95, 0x00, 0xfb, 0xe5, 0x00, 0x95, 0x00, 0xfa, 0xe4, 0x95, 0x00,
0xf9, 0xe4, 0x95, 0x00, 0x22, 0xe5, 0x00, 0x25, 0x00, 0xff, 0xe5, 0x00, 0x35, 0x00, 0xfe, 0xe4,
0x35, 0x00, 0xfd, 0xe4, 0x35, 0x00, 0xfc, 0x22, 0x7e, 0x00, 0x7f, 0x06, 0x7d, 0x00, 0x7b, 0xfe,
0x02, 0x10, 0x98, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0x12, 0x10, 0x17, 0x12, 0x0e, 0xb7, 0xe4, 0x7b,
0x02, 0xfa, 0xf9, 0xf8, 0x22, 0xf8, 0xe2, 0x2f, 0xf5, 0x28, 0x18, 0xe2, 0x3e, 0xf5, 0x27, 0x22,
0xea, 0x33, 0x95, 0xe0, 0xf9, 0xf8, 0xe4, 0xfc, 0xfd, 0x02, 0x0e, 0xb7, 0x85, 0x0d, 0x82, 0x85,
0x0c, 0x83, 0x74, 0x05, 0x93, 0x22, 0xff, 0xed, 0x33, 0x95, 0xe0, 0xfc, 0xef, 0x2d, 0xff, 0xe4,
0x3c, 0xc3, 0x13, 0xef, 0x13, 0x22, 0x24, 0x03, 0xf8, 0xec, 0xf2, 0x08, 0xed, 0xf2, 0x22, 0xf5,
0x83, 0xe5, 0x82, 0x2d, 0xf5, 0x82, 0xe5, 0x83, 0x3c, 0xf5, 0x83, 0xef, 0xf0, 0x22, 0xe5, 0x00,
0x25, 0xe0, 0x24, 0x69, 0xf8, 0xe6, 0x22, 0xf5, 0x00, 0xea, 0x3e, 0xf5, 0x00, 0xe9, 0x3d, 0xf5,
0x00, 0xe8, 0x3c, 0xf5, 0x00, 0x22, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x05, 0xf8, 0xe2, 0x22, 0x74,
0x1e, 0x93, 0xfe, 0xa8, 0x07, 0xe8, 0x24, 0x0e, 0xf8, 0xe2, 0xc3, 0x9e, 0x22, 0x24, 0x02, 0xf8,
0xc3, 0xe2, 0x9d, 0xf5, 0x29, 0x18, 0xe2, 0x9c, 0xf5, 0x28, 0x22, 0x24, 0x04, 0xf8, 0xc3, 0xe2,
0x9d, 0xf5, 0x2b, 0x18, 0xe2, 0x9c, 0xf5, 0x2a, 0x22, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0x2f, 0xff,
0xee, 0x3c, 0xfe, 0xef, 0x78, 0x02, 0x22, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x04, 0x22, 0xff, 0xae,
0xf0, 0xe4, 0xfc, 0xfd, 0x22, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x2b, 0x22, 0x78, 0x66, 0xe6, 0x24,
0x0f, 0xf8, 0x22, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xe9, 0x3d, 0xfd, 0xe8, 0x3c, 0xfc, 0x22,
0xef, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x01, 0xf8, 0x22, 0xe4, 0x7f, 0x01, 0xfe, 0xfd, 0xfc, 0x22,
0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0x22, 0xc3, 0xe5, 0x00, 0x9f, 0xf5, 0x00, 0xe5, 0x00, 0x9e,
0xf5, 0x00, 0x22, 0x78, 0x53, 0x12, 0x10, 0x0b, 0x78, 0x4f, 0x12, 0x10, 0x17, 0xeb, 0x22, 0xe5,
0x30, 0x25, 0x30, 0xf5, 0x30, 0xe5, 0x2f, 0x33, 0xf5, 0x2f, 0x22, 0xc3, 0xe5, 0x26, 0x95, 0x28,
0xff, 0xe5, 0x25, 0x95, 0x27, 0xfe, 0x22, 0xe5, 0x00, 0xf0, 0xa3, 0xe5, 0x00, 0xf0, 0x22, 0xf9,
0x7a, 0x00, 0x7b, 0xfe, 0x75, 0xf0, 0x02, 0xe5, 0x00, 0x22, 0x13, 0xfb, 0xaa, 0x06, 0xe4, 0xf9,
0xf8, 0x22, 0xf8, 0xe4, 0xf2, 0x08, 0x74, 0x80, 0xf2, 0xa8, 0x07, 0xe8, 0x22, 0xe4, 0xfc, 0xfd,
0xeb, 0x25, 0x00, 0xff, 0xea, 0x35, 0x00, 0x22, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x02, 0x22, 0xce,
0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0x78, 0x66, 0xe6, 0x24, 0x1a, 0xf8, 0x22, 0x78, 0x66, 0xe6,
0x24, 0x0d, 0xf8, 0x22, 0xd3, 0xe5, 0x35, 0x95, 0x37, 0xe5, 0x34, 0x95, 0x36, 0x22, 0x33, 0xfe,
0x7c, 0x00, 0x7d, 0x03, 0x02, 0x0d, 0x1a, 0x24, 0x40, 0xff, 0xe4, 0x3e, 0xfe, 0x22, 0xe5, 0x00,
0x25, 0xe0, 0x24, 0x68, 0x22, 0xe5, 0x00, 0x25, 0xe0, 0x24, 0x69, 0x22, 0x8f, 0x22, 0x8d, 0x23,
0x12, 0x04, 0xd6, 0x70, 0x03, 0x02, 0x0b, 0x41, 0x12, 0x00, 0x60, 0x12, 0x04, 0xdf, 0x50, 0x06,
0x12, 0x00, 0x9a, 0x02, 0x07, 0x1f, 0x12, 0x05, 0xcd, 0xe2, 0x70, 0x50, 0x12, 0x05, 0x25, 0x12,
0x01, 0x14, 0x12, 0x04, 0xed, 0x12, 0x01, 0x0e, 0x12, 0x04, 0xfb, 0x12, 0x00, 0x60, 0x74, 0x17,
0x93, 0x75, 0x34, 0x00, 0xf5, 0x35, 0xaf, 0x2b, 0xae, 0x2a, 0x12, 0x39, 0xa3, 0xc0, 0x06, 0xc0,
0x07, 0xaf, 0x29, 0xae, 0x28, 0x12, 0x39, 0xa3, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe,
0xd3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x40, 0x08, 0x12, 0x05, 0xcd, 0x74, 0x01, 0xf2, 0x80,
0x23, 0xe4, 0xf5, 0x28, 0xf5, 0x29, 0xf5, 0x2a, 0xf5, 0x2b, 0x80, 0x18, 0x78, 0x66, 0xe6, 0xff,
0x24, 0x07, 0x12, 0x01, 0x14, 0x12, 0x04, 0xed, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x09, 0x12, 0x01,
0x14, 0x12, 0x04, 0xfb, 0x12, 0x04, 0x10, 0xc0, 0x04, 0x12, 0x01, 0x30, 0x78, 0x66, 0xe6, 0x24,
0x16, 0x12, 0x00, 0xf3, 0x12, 0x03, 0xd3, 0xd0, 0x00, 0x12, 0x0e, 0xb7, 0xc0, 0x04, 0xc0, 0x05,
0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x23, 0xab, 0x07, 0xae, 0x28, 0xaf, 0x29, 0x12, 0x03, 0xcf, 0x12,
0x0e, 0xb7, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x12, 0x02, 0x33, 0x12, 0x33, 0x10,
0x8e, 0x28, 0x8f, 0x29, 0x12, 0x04, 0x10, 0xc0, 0x04, 0x12, 0x01, 0x30, 0x78, 0x66, 0xe6, 0x24,
0x18, 0x12, 0x00, 0xf3, 0x12, 0x03, 0xd3, 0xd0, 0x00, 0x12, 0x0e, 0xb7, 0xc0, 0x04, 0xc0, 0x05,
0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x23, 0xab, 0x07, 0xae, 0x2a, 0xaf, 0x2b, 0x12, 0x03, 0xcf, 0x12,
0x0e, 0xb7, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x12, 0x02, 0x33, 0x12, 0x33, 0x10,
0x8e, 0x2a, 0x8f, 0x2b, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x16, 0xf8, 0xe5, 0x28, 0xf2, 0x08, 0xe5,
0x29, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x18, 0xf8, 0xe5, 0x2a, 0xf2, 0x08, 0xe5, 0x2b, 0xf2, 0x12,
0x00, 0x60, 0x74, 0x1e, 0x93, 0xff, 0x12, 0x02, 0xfc, 0x9f, 0x50, 0x03, 0x02, 0x0b, 0x1a, 0x78,
0x66, 0xe6, 0xfb, 0x24, 0x07, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0xfd, 0xac, 0x06, 0xe5, 0x28, 0xa2,
0xe7, 0x13, 0xfe, 0xe5, 0x29, 0x12, 0x02, 0xcb, 0xa8, 0x03, 0xe8, 0x04, 0x12, 0x05, 0x09, 0x12,
0x05, 0xbf, 0xd8, 0xfb, 0xff, 0x12, 0x00, 0x60, 0x74, 0x01, 0x93, 0xfc, 0x74, 0x02, 0x93, 0xfd,
0x12, 0x35, 0x58, 0x8e, 0x24, 0x8f, 0x25, 0x78, 0x66, 0xe6, 0xfb, 0x24, 0x09, 0xf8, 0xe2, 0xfe,
0x08, 0xe2, 0xfd, 0xac, 0x06, 0xe5, 0x2a, 0xa2, 0xe7, 0x13, 0xfe, 0xe5, 0x2b, 0x12, 0x02, 0xcb,
0xa8, 0x03, 0xe8, 0x24, 0x03, 0x12, 0x05, 0x09, 0x12, 0x05, 0xbf, 0xd8, 0xfb, 0xff, 0x12, 0x00,
0x60, 0x74, 0x03, 0x93, 0xfc, 0x74, 0x04, 0x93, 0xfd, 0x12, 0x35, 0x58, 0x8e, 0x26, 0x8f, 0x27,
0x12, 0x00, 0x60, 0x74, 0x1e, 0x93, 0x24, 0x0a, 0xff, 0xe4, 0x33, 0xfe, 0x78, 0x66, 0xe6, 0xfd,
0x24, 0x0e, 0xf8, 0xe2, 0xc3, 0x9f, 0xee, 0x64, 0x80, 0xf8, 0x74, 0x80, 0x98, 0x50, 0x59, 0xa8,
0x05, 0xe8, 0x24, 0x16, 0x12, 0x00, 0xf3, 0x12, 0x39, 0xa3, 0x12, 0x00, 0x60, 0x74, 0x1e, 0x93,
0xfd, 0x78, 0x66, 0xe6, 0xf9, 0x24, 0x0e, 0xf8, 0xe2, 0xc3, 0x12, 0x04, 0x1e, 0x24, 0x8d, 0xf5,
0x82, 0xe4, 0x34, 0x00, 0x12, 0x04, 0xaf, 0xa8, 0x01, 0xe8, 0x24, 0x18, 0x12, 0x00, 0xf3, 0x12,
0x39, 0xa3, 0x12, 0x00, 0x60, 0x74, 0x1e, 0x93, 0xfd, 0x12, 0x02, 0xfc, 0x12, 0x04, 0x1e, 0x24,
0xa1, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x12, 0x04, 0xaf, 0x75, 0x38, 0x00, 0x75, 0x39, 0x80, 0x75,
0x3a, 0x00, 0x75, 0x3b, 0x80, 0x02, 0x09, 0x89, 0x12, 0x04, 0x24, 0x24, 0x96, 0xf9, 0x74, 0x00,
0x35, 0xf0, 0xfa, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x78, 0x66, 0xe6, 0x24, 0x16,
0x12, 0x00, 0xf3, 0x12, 0x39, 0xa3, 0xad, 0x07, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x12, 0x34,
0x7a, 0x8e, 0x34, 0x8f, 0x35, 0x12, 0x04, 0x24, 0x24, 0xaa, 0xf9, 0x74, 0x00, 0x35, 0xf0, 0xfa,
0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x78, 0x66, 0xe6, 0x24, 0x18, 0x12, 0x00, 0xf3,
0x12, 0x39, 0xa3, 0xad, 0x07, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x12, 0x34, 0x7a, 0x8e, 0x36,
0x8f, 0x37, 0x12, 0x05, 0xd4, 0x40, 0x18, 0xe5, 0x35, 0xae, 0x34, 0x78, 0x03, 0xc3, 0x33, 0xce,
0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe5, 0x37, 0x24, 0x01, 0xfd, 0xe4, 0x35, 0x36, 0x80, 0x16, 0xe5,
0x37, 0xae, 0x36, 0x78, 0x03, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe5, 0x35, 0x24,
0x01, 0xfd, 0xe4, 0x35, 0x34, 0xfc, 0x12, 0x0d, 0x1a, 0xab, 0x07, 0xaa, 0x06, 0x78, 0x66, 0xe6,
0xf9, 0x24, 0x10, 0x12, 0x00, 0xf3, 0x12, 0x02, 0xd1, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xef,
0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xfb, 0xaa, 0x06, 0xc3, 0x94, 0x28, 0xea,
0x94, 0x00, 0x50, 0x06, 0x7a, 0x00, 0x7b, 0x28, 0x80, 0x0d, 0xd3, 0xeb, 0x94, 0x46, 0xea, 0x94,
0x00, 0x40, 0x04, 0x7a, 0x00, 0x7b, 0x46, 0x7c, 0x00, 0x7d, 0x0a, 0xaf, 0x03, 0xae, 0x02, 0x12,
0x0d, 0x08, 0xef, 0x24, 0xf0, 0xf5, 0x39, 0xee, 0x34, 0xfe, 0xf5, 0x38, 0xeb, 0x25, 0xe0, 0xff,
0xea, 0x33, 0xfe, 0xc3, 0x74, 0xd0, 0x9f, 0xf5, 0x3b, 0xe4, 0x9e, 0xf5, 0x3a, 0x12, 0x05, 0xd4,
0x40, 0x12, 0x85, 0x38, 0x34, 0x85, 0x39, 0x35, 0x85, 0x3a, 0x38, 0x85, 0x3b, 0x39, 0x85, 0x34,
0x3a, 0x85, 0x35, 0x3b, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x10, 0xf8, 0xea, 0xf2, 0x08, 0xeb, 0xf2,
0xa8, 0x07, 0xe8, 0x24, 0x12, 0x12, 0x00, 0xf3, 0x12, 0x02, 0xd1, 0xe5, 0x39, 0x2f, 0xff, 0xe5,
0x38, 0x3e, 0xfe, 0xef, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xf5, 0x39, 0x8e,
0x38, 0x78, 0x66, 0xe6, 0xfb, 0x24, 0x14, 0x12, 0x00, 0xf3, 0x12, 0x02, 0xd1, 0xe5, 0x3b, 0x2f,
0xff, 0xe5, 0x3a, 0x3e, 0xfe, 0xef, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xf5,
0x3b, 0x8e, 0x3a, 0xeb, 0x24, 0x12, 0xf8, 0xe5, 0x38, 0xf2, 0x08, 0xe5, 0x39, 0xf2, 0xe9, 0x24,
0x14, 0xf8, 0xe5, 0x3a, 0xf2, 0x08, 0xe5, 0x3b, 0xf2, 0x12, 0x0b, 0x70, 0x7c, 0x00, 0x7d, 0x02,
0x12, 0x0d, 0x6f, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x0b, 0x84, 0xd0, 0xe0, 0x2f, 0xf5, 0x35, 0xd0,
0xe0, 0x3e, 0xf5, 0x34, 0x12, 0x00, 0x60, 0xae, 0x34, 0xaf, 0x35, 0x12, 0x03, 0xda, 0x25, 0x35,
0xf5, 0x35, 0xee, 0x35, 0x34, 0xf5, 0x34, 0xd3, 0xe5, 0x35, 0x95, 0x39, 0xe5, 0x34, 0x95, 0x38,
0x40, 0x06, 0x85, 0x38, 0x34, 0x85, 0x39, 0x35, 0x78, 0x66, 0xe6, 0x24, 0x07, 0x12, 0x00, 0xf3,
0xc3, 0xe5, 0x39, 0x95, 0x35, 0xfd, 0xe5, 0x38, 0x95, 0x34, 0xfc, 0x12, 0x10, 0x6b, 0x8f, 0x2f,
0x8e, 0x2e, 0x8d, 0x2d, 0x8c, 0x2c, 0xae, 0x24, 0xaf, 0x25, 0xab, 0x07, 0xaa, 0x06, 0xae, 0x34,
0xaf, 0x35, 0x12, 0x04, 0x80, 0xef, 0x25, 0x2f, 0xff, 0xee, 0x35, 0x2e, 0xfe, 0xed, 0x35, 0x2d,
0xfd, 0xec, 0x35, 0x2c, 0xfc, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x38, 0xc3, 0x13, 0xfe, 0xe5, 0x39,
0x12, 0x05, 0x9a, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x05, 0x33, 0xc0, 0x06, 0xc0, 0x07, 0xae, 0x38,
0xaf, 0x39, 0xab, 0x07, 0xaa, 0x06, 0xe4, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x0f, 0x42, 0x8f, 0x2f,
0x8e, 0x2e, 0x8d, 0x2d, 0x8c, 0x2c, 0x12, 0x0b, 0x84, 0x7c, 0x00, 0x7d, 0x02, 0x12, 0x0d, 0x6f,
0xc0, 0x06, 0xc0, 0x07, 0x12, 0x0b, 0x70, 0xd0, 0xe0, 0x2f, 0xf5, 0x37, 0xd0, 0xe0, 0x3e, 0xf5,
0x36, 0x12, 0x00, 0x60, 0xae, 0x36, 0xaf, 0x37, 0x12, 0x03, 0xda, 0x25, 0x37, 0xf5, 0x37, 0xee,
0x35, 0x36, 0xf5, 0x36, 0xd3, 0xe5, 0x37, 0x95, 0x3b, 0xe5, 0x36, 0x95, 0x3a, 0x40, 0x06, 0x85,
0x3a, 0x36, 0x85, 0x3b, 0x37, 0x78, 0x66, 0xe6, 0x24, 0x09, 0x12, 0x00, 0xf3, 0xc3, 0xe5, 0x3b,
0x95, 0x37, 0xfd, 0xe5, 0x3a, 0x95, 0x36, 0xfc, 0x12, 0x10, 0x6b, 0x8f, 0x33, 0x8e, 0x32, 0x8d,
0x31, 0x8c, 0x30, 0xae, 0x26, 0xaf, 0x27, 0xab, 0x07, 0xaa, 0x06, 0xae, 0x36, 0xaf, 0x37, 0x12,
0x04, 0x80, 0xef, 0x25, 0x33, 0xff, 0xee, 0x35, 0x32, 0xfe, 0xed, 0x35, 0x31, 0xfd, 0xec, 0x35,
0x30, 0xfc, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3a, 0xc3, 0x13, 0xfe, 0xe5, 0x3b, 0x12, 0x05, 0x9a,
0xd0, 0x07, 0xd0, 0x06, 0x12, 0x05, 0x33, 0xc0, 0x06, 0xc0, 0x07, 0xae, 0x3a, 0xaf, 0x3b, 0xab,
0x07, 0xaa, 0x06, 0xe4, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x0f, 0x42, 0x8f, 0x33, 0x8e, 0x32, 0x8d,
0x31, 0x8c, 0x30, 0x12, 0x00, 0x60, 0x74, 0x16, 0x93, 0xf4, 0x60, 0x2e, 0x78, 0x66, 0xe6, 0xff,
0x24, 0x0d, 0xf8, 0xe2, 0xb4, 0x01, 0x1b, 0xa8, 0x07, 0xe8, 0x04, 0xf8, 0xe5, 0x2e, 0xf2, 0x08,
0xe5, 0x2f, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x03, 0xf8, 0xe5, 0x32, 0xf2, 0x08, 0xe5, 0x33, 0xf2,
0x80, 0x08, 0x78, 0x66, 0x12, 0x00, 0xfa, 0x12, 0x04, 0xa6, 0x78, 0x66, 0xe6, 0xff, 0x04, 0x12,
0x01, 0x14, 0x24, 0x07, 0x12, 0x04, 0xa8, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x03, 0x12, 0x01, 0x14,
0x12, 0x02, 0xf4, 0x94, 0x14, 0x50, 0x03, 0xe2, 0x04, 0xf2, 0x12, 0x05, 0x2c, 0x74, 0x01, 0xf2,
0x22, 0x12, 0x05, 0x2c, 0xe2, 0xd3, 0x94, 0x00, 0x40, 0x03, 0xe2, 0x14, 0xf2, 0xe2, 0x70, 0x1f,
0x78, 0x66, 0xe6, 0xff, 0x24, 0x0e, 0xf8, 0xe4, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x12, 0x12, 0x05,
0xa2, 0x24, 0x14, 0x12, 0x05, 0xa2, 0x24, 0x10, 0xf8, 0xe4, 0xf2, 0x08, 0x74, 0x28, 0xf2, 0x22,
0x78, 0x66, 0xe6, 0x24, 0x0a, 0xf8, 0xc3, 0xe2, 0x95, 0x27, 0xff, 0x18, 0xe2, 0x95, 0x26, 0xfe,
0x12, 0x39, 0xa3, 0x22, 0x78, 0x66, 0xe6, 0x24, 0x08, 0xf8, 0xc3, 0xe2, 0x95, 0x25, 0xff, 0x18,
0xe2, 0x95, 0x24, 0xfe, 0x12, 0x39, 0xa3, 0x22, 0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46,
0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3,
0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08,
0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64,
0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83,
0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4,
0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8,
0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93,
0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc,
0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3,
0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec,
0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82,
0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4,
0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60,
0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02,
0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x0b, 0xe8, 0x73, 0xbb, 0x01,
0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22,
0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5,
0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe,
0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5,
0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7,
0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5,
0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb,
0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c,
0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, 0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29,
0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, 0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f,
0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, 0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d,
0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, 0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20,
0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07,
0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, 0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xc2,
0xd5, 0xec, 0x30, 0xe7, 0x09, 0xb2, 0xd5, 0xe4, 0xc3, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0xee, 0x30,
0xe7, 0x15, 0xb2, 0xd5, 0xe4, 0xc3, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x12, 0x0d, 0x1a, 0xc3, 0xe4,
0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0x80, 0x03, 0x12, 0x0d, 0x1a, 0x30, 0xd5, 0x07, 0xc3, 0xe4, 0x9f,
0xff, 0xe4, 0x9e, 0xfe, 0x22, 0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5,
0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82,
0x8a, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x06, 0x87, 0xf0, 0x09, 0xe7, 0x19, 0x22,
0xbb, 0xfe, 0x07, 0xe3, 0xf5, 0xf0, 0x09, 0xe3, 0x19, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93,
0xf5, 0xf0, 0x74, 0x01, 0x93, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83,
0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86,
0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2,
0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 0xbb, 0x01,
0x0d, 0xc5, 0x82, 0x29, 0xc5, 0x82, 0xc5, 0x83, 0x3a, 0xc5, 0x83, 0x02, 0x0d, 0xa5, 0x50, 0x11,
0xc5, 0x82, 0x29, 0xf8, 0x08, 0xe5, 0xf0, 0x26, 0xf6, 0x18, 0xf5, 0xf0, 0xe5, 0x82, 0x36, 0xf6,
0x22, 0xbb, 0xfe, 0x11, 0xc5, 0x82, 0x29, 0xf8, 0x08, 0xe2, 0x25, 0xf0, 0xf5, 0xf0, 0xf2, 0x18,
0xe2, 0x35, 0x82, 0xf2, 0x22, 0xf8, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x2a, 0xf5, 0x83,
0x74, 0x01, 0x93, 0x25, 0xf0, 0xf5, 0xf0, 0xe4, 0x93, 0x38, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82,
0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22,
0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82,
0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50,
0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82,
0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, 0x2c,
0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, 0xf0,
0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, 0xf0,
0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, 0xf0,
0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, 0x35,
0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee,
0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a,
0xec, 0x99, 0xe5, 0x82, 0x98, 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec,
0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8,
0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf,
0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed,
0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99,
0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe,
0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40,
0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb,
0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc,
0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd,
0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa,
0xe4, 0xc8, 0xf9, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0,
0xe8, 0x9c, 0x45, 0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee,
0x13, 0xfe, 0xef, 0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, 0xee,
0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe6, 0xfc, 0x08, 0xe6, 0xfd,
0x08, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xf9, 0x08, 0xe6, 0xfa, 0x08,
0xe6, 0xcb, 0xf8, 0x22, 0xe4, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf9, 0x74, 0x02, 0x93, 0xfa, 0x74,
0x03, 0x93, 0xfb, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0x22,
0xd0, 0x83, 0xd0, 0x82, 0xe4, 0x93, 0xf6, 0x08, 0x74, 0x01, 0x93, 0xf6, 0x08, 0x74, 0x02, 0x93,
0xf6, 0x08, 0x74, 0x03, 0x93, 0xf6, 0x74, 0x04, 0x73, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0,
0x35, 0x83, 0xf5, 0x83, 0x22, 0x8a, 0x83, 0x89, 0x82, 0xe4, 0x73, 0xec, 0x8e, 0xf0, 0xa4, 0xcc,
0xc5, 0xf0, 0xcc, 0xcd, 0xf8, 0xef, 0xa4, 0xce, 0xc5, 0xf0, 0x2d, 0xfd, 0xe4, 0x3c, 0xfc, 0xe8,
0xa4, 0x2e, 0xc8, 0xc5, 0xf0, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0xef, 0xa4, 0xff, 0xe5, 0xf0, 0x28,
0xfe, 0xe4, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0xef, 0x4e, 0x60, 0x12, 0xef, 0x60, 0x01, 0x0e,
0xed, 0xbb, 0x01, 0x0b, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x22, 0x89,
0xf0, 0x50, 0x07, 0xf7, 0x09, 0xdf, 0xfc, 0xa9, 0xf0, 0x22, 0xbb, 0xfe, 0xfc, 0xf3, 0x09, 0xdf,
0xfc, 0xa9, 0xf0, 0x22, 0x90, 0x36, 0x03, 0x7d, 0x1f, 0x12, 0x31, 0xda, 0xee, 0x44, 0x80, 0xf5,
0x8f, 0x8f, 0x8e, 0x75, 0x8a, 0xa0, 0x75, 0x8a, 0x0a, 0xe4, 0x90, 0x00, 0xc3, 0xf0, 0x90, 0x00,
0xc9, 0xe0, 0x70, 0x03, 0x02, 0x11, 0xd7, 0x14, 0x70, 0x03, 0x02, 0x12, 0x02, 0x24, 0xfc, 0x70,
0x03, 0x02, 0x13, 0x49, 0x04, 0x60, 0x03, 0x02, 0x13, 0x82, 0xe4, 0xf5, 0x18, 0x78, 0x6e, 0xf6,
0x90, 0x36, 0x12, 0x93, 0x70, 0x0e, 0x75, 0x0a, 0x36, 0x75, 0x0b, 0x2a, 0x12, 0x39, 0xb9, 0x8f,
0x18, 0x02, 0x11, 0xc6, 0xe4, 0xf5, 0x1a, 0xf5, 0x1b, 0x75, 0x0a, 0x38, 0x75, 0x0b, 0x9e, 0x12,
0x14, 0x75, 0x12, 0x31, 0xc7, 0x12, 0x20, 0x0b, 0xe4, 0xf5, 0x19, 0x12, 0x31, 0xac, 0xe4, 0x93,
0xff, 0xe5, 0x19, 0xc3, 0x9f, 0x50, 0x33, 0xaf, 0x19, 0x12, 0x39, 0xc9, 0xac, 0x06, 0xad, 0x07,
0x12, 0x31, 0xac, 0x74, 0x2c, 0x93, 0x75, 0xf0, 0xc8, 0xa4, 0xff, 0xd3, 0xed, 0x9f, 0xec, 0x95,
0xf0, 0x40, 0x13, 0xe4, 0x7f, 0x01, 0xfe, 0xfd, 0xfc, 0xa9, 0x19, 0xa8, 0x01, 0x12, 0x0f, 0xf8,
0xef, 0x42, 0x1b, 0xee, 0x42, 0x1a, 0x05, 0x19, 0x80, 0xc1, 0xe5, 0x1a, 0x90, 0x01, 0xab, 0xf0,
0xa3, 0xe5, 0x1b, 0xf0, 0xe4, 0xf5, 0x19, 0xae, 0x1a, 0xaf, 0x1b, 0xe4, 0xfc, 0xfd, 0xe5, 0x19,
0x25, 0xe0, 0x25, 0xe0, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x36, 0xf5, 0x83, 0x12, 0x10, 0x24,
0xc3, 0x12, 0x0f, 0xd4, 0x60, 0x07, 0x05, 0x19, 0xe5, 0x19, 0xb4, 0x04, 0xda, 0xe5, 0x19, 0xc3,
0x94, 0x04, 0x50, 0x19, 0x85, 0x19, 0x18, 0x75, 0xf0, 0x9d, 0xe5, 0x19, 0xa4, 0x24, 0x2a, 0xf5,
0x82, 0xe5, 0xf0, 0x34, 0x36, 0xaf, 0x82, 0xf5, 0x0a, 0x8f, 0x0b, 0x80, 0x09, 0xe4, 0xf5, 0x18,
0x75, 0x0a, 0x36, 0x75, 0x0b, 0x2a, 0x90, 0x01, 0xaa, 0xe5, 0x18, 0xf0, 0x90, 0x01, 0xf0, 0x74,
0x40, 0xf0, 0xa3, 0xf0, 0x02, 0x13, 0x82, 0xe4, 0x78, 0x6e, 0xf6, 0x12, 0x2f, 0xde, 0xef, 0x64,
0x01, 0x60, 0xf8, 0x12, 0x14, 0x75, 0xaf, 0x0b, 0xae, 0x0a, 0x12, 0x00, 0x1f, 0xe5, 0x0b, 0x24,
0x79, 0xff, 0xe4, 0x35, 0x0a, 0xfe, 0x12, 0x39, 0x3b, 0x12, 0x31, 0xe4, 0xa3, 0x04, 0xf0, 0x02,
0x13, 0x87, 0xe4, 0xf5, 0x18, 0x78, 0x42, 0xf6, 0x90, 0x01, 0xff, 0xe0, 0xb4, 0x01, 0x09, 0x90,
0x00, 0xc9, 0x74, 0x05, 0xf0, 0x02, 0x13, 0x87, 0x78, 0x6e, 0x76, 0x01, 0x12, 0x31, 0xc7, 0x12,
0x20, 0x0b, 0x78, 0x42, 0xa6, 0x07, 0x12, 0x31, 0xac, 0x74, 0x63, 0x93, 0x70, 0x03, 0x74, 0x62,
0x93, 0x60, 0x1b, 0x08, 0xe6, 0xf5, 0x19, 0x08, 0xe6, 0xf5, 0x1a, 0x08, 0xe6, 0xfe, 0x08, 0xe6,
0xff, 0x78, 0x43, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x08, 0xa6, 0x19, 0x08, 0xa6, 0x1a, 0x7f, 0x5f,
0xe5, 0x0b, 0x24, 0x79, 0xfd, 0xe4, 0x35, 0x0a, 0xfc, 0x12, 0x2c, 0xe4, 0x8f, 0x18, 0x12, 0x31,
0xc7, 0x75, 0x20, 0x36, 0x75, 0x21, 0x23, 0xad, 0x18, 0x12, 0x1b, 0x15, 0x8f, 0x18, 0xe4, 0x78,
0x42, 0xf6, 0x78, 0x47, 0xe6, 0x70, 0x03, 0x02, 0x12, 0xfc, 0xe5, 0x18, 0x70, 0x12, 0x90, 0x01,
0xea, 0xe0, 0x30, 0xe2, 0x0b, 0x78, 0x89, 0xe2, 0x24, 0x01, 0xf2, 0x18, 0xe2, 0x34, 0x00, 0xf2,
0x78, 0x4d, 0xe6, 0x60, 0x07, 0x90, 0x01, 0xea, 0xe0, 0x20, 0xe0, 0x0c, 0xe5, 0x18, 0xb4, 0xaa,
0x0f, 0x90, 0x01, 0xea, 0xe0, 0x30, 0xe1, 0x08, 0x90, 0x00, 0xc8, 0xe0, 0x04, 0xf0, 0x80, 0x08,
0x90, 0x00, 0xc8, 0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x36, 0x08, 0xe4, 0x93, 0x75, 0xf0, 0x64,
0xa4, 0xff, 0xd3, 0x78, 0x89, 0xe2, 0x9f, 0x18, 0xe2, 0x95, 0xf0, 0x50, 0x1b, 0x12, 0x31, 0xac,
0x74, 0x9c, 0x93, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0x90, 0x00, 0xc8, 0xe0, 0xd3, 0x9f, 0xee,
0x64, 0x80, 0xf8, 0x74, 0x80, 0x98, 0x40, 0x14, 0x7f, 0x01, 0x12, 0x39, 0xc4, 0xe4, 0x78, 0x47,
0xf6, 0x78, 0x4d, 0xf6, 0x78, 0x48, 0x76, 0x04, 0x78, 0x4e, 0x76, 0x04, 0x12, 0x31, 0xc7, 0x78,
0x42, 0xe6, 0xf5, 0x20, 0xad, 0x18, 0x12, 0x18, 0xf2, 0x78, 0x47, 0xe6, 0x60, 0x19, 0x90, 0x36,
0x06, 0x7d, 0x64, 0x12, 0x31, 0xda, 0xc3, 0x78, 0x70, 0xe6, 0x9f, 0x18, 0xe6, 0x9e, 0x50, 0x67,
0xa6, 0x06, 0x08, 0xa6, 0x07, 0x80, 0x60, 0x90, 0x01, 0xfe, 0xe0, 0x70, 0x17, 0x78, 0x70, 0xe6,
0x18, 0x46, 0x60, 0x09, 0x08, 0xe6, 0x16, 0x18, 0x70, 0x0a, 0x16, 0x80, 0x07, 0x78, 0x6f, 0x76,
0x00, 0x08, 0x76, 0x14, 0x12, 0x31, 0xe4, 0x80, 0x3e, 0x12, 0x31, 0xac, 0xe4, 0x93, 0x90, 0x01,
0xcb, 0xf0, 0x90, 0x01, 0xff, 0xe0, 0xb4, 0x01, 0x2e, 0x75, 0x1f, 0x01, 0x75, 0x20, 0x01, 0x75,
0x21, 0x40, 0x75, 0x22, 0x01, 0x75, 0x23, 0x01, 0x75, 0x24, 0x80, 0x7b, 0x01, 0x7a, 0x01, 0x79,
0xc0, 0x12, 0x1c, 0xd8, 0xe4, 0x90, 0x01, 0xff, 0xf0, 0x75, 0x8a, 0xa0, 0x90, 0x00, 0xc0, 0xf0,
0x80, 0xd0, 0xe4, 0x90, 0x00, 0xc9, 0xf0, 0x90, 0x01, 0xe5, 0xe0, 0x64, 0x03, 0x60, 0x0b, 0x90,
0x01, 0xb5, 0xe0, 0x64, 0x03, 0x60, 0x03, 0x02, 0x14, 0x20, 0x90, 0x36, 0x0e, 0xe4, 0x93, 0xf5,
0x18, 0x7f, 0x01, 0x12, 0x35, 0x32, 0xe5, 0x18, 0x70, 0x05, 0x90, 0xff, 0x11, 0x80, 0x0d, 0xe5,
0x18, 0xb4, 0x01, 0x0c, 0x90, 0xff, 0x10, 0xe0, 0x44, 0x18, 0xf0, 0xa3, 0xe0, 0x44, 0x18, 0xf0,
0x90, 0x01, 0xb5, 0xe0, 0xb4, 0x03, 0x15, 0x90, 0xff, 0x12, 0xe0, 0x54, 0xe3, 0xf0, 0x90, 0xff,
0x11, 0xe0, 0x54, 0xe3, 0xf0, 0x90, 0xff, 0x10, 0xe0, 0x54, 0xe3, 0xf0, 0x75, 0x8f, 0x87, 0x75,
0x8e, 0xff, 0x75, 0x8d, 0x87, 0x75, 0x8c, 0xff, 0x12, 0x31, 0xbe, 0x75, 0x8a, 0xa0, 0xf0, 0xe5,
0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x75, 0x91, 0xc3, 0xe4,
0xf5, 0x91, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12,
0x31, 0xbe, 0x75, 0x8a, 0xa0, 0xf0, 0x75, 0x8a, 0xa0, 0xf0, 0x75, 0x8a, 0xa0, 0xf0, 0x80, 0xc8,
0x75, 0x18, 0x27, 0x75, 0x19, 0x10, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03,
0xe0, 0x04, 0xf0, 0x90, 0x00, 0xc3, 0xe0, 0xff, 0xc3, 0x78, 0x6e, 0x96, 0x50, 0x36, 0xe5, 0x19,
0x15, 0x19, 0xac, 0x18, 0x70, 0x02, 0x15, 0x18, 0x4c, 0x60, 0x29, 0xe5, 0x89, 0x30, 0xe7, 0x0c,
0x75, 0x89, 0x80, 0xef, 0xc3, 0x94, 0xff, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x75, 0x91, 0xc1, 0xe4,
0xf5, 0x91, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12,
0x31, 0xbe, 0x80, 0xbf, 0x22, 0xaf, 0x0b, 0xae, 0x0a, 0x12, 0x22, 0xe9, 0xaf, 0x0b, 0xae, 0x0a,
0x12, 0x35, 0x7b, 0x22, 0x75, 0x89, 0x80, 0x90, 0x00, 0xc3, 0xe0, 0xc3, 0x94, 0xff, 0x22, 0x43,
0xad, 0x04, 0x90, 0xff, 0x50, 0x74, 0x0f, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x85, 0x0d, 0x82, 0x85,
0x0c, 0x83, 0x74, 0x26, 0x93, 0x90, 0xff, 0x48, 0xf0, 0x85, 0x0d, 0x82, 0x85, 0x0c, 0x83, 0x74,
0x27, 0x93, 0x90, 0xff, 0x42, 0xf0, 0x90, 0xff, 0x40, 0x74, 0x6c, 0xf0, 0x90, 0xff, 0x57, 0x74,
0xff, 0xf0, 0x90, 0xff, 0x56, 0xe4, 0xf0, 0x90, 0xff, 0x5f, 0x74, 0xff, 0xf0, 0x90, 0xff, 0x5e,
0xe4, 0xf0, 0x85, 0x0d, 0x82, 0x85, 0x0c, 0x83, 0x22, 0x78, 0x5c, 0xe6, 0xff, 0x78, 0x84, 0xe2,
0xfc, 0x08, 0xe2, 0x2f, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0x22, 0xe5, 0x22, 0x75, 0xf0,
0x0a, 0xa4, 0x24, 0x03, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0x90, 0xff, 0x54, 0xe0,
0x90, 0x01, 0xf0, 0xf0, 0x90, 0xff, 0x5c, 0xe0, 0x90, 0x01, 0xf1, 0xf0, 0x75, 0x8a, 0xa0, 0xe4,
0x90, 0x00, 0xc0, 0xf0, 0x8c, 0x8f, 0x8d, 0x8e, 0x75, 0x8a, 0xa0, 0xf0, 0x90, 0xff, 0x43, 0x74,
0x5f, 0xf0, 0xe5, 0x89, 0x22, 0xe5, 0x27, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4,
0x34, 0x02, 0xf5, 0x83, 0x22, 0x78, 0x5c, 0xe6, 0xff, 0x24, 0xb7, 0xf5, 0x82, 0xe4, 0x34, 0x02,
0xf5, 0x83, 0xe0, 0x90, 0xff, 0x54, 0xf0, 0x18, 0xe6, 0x24, 0xb7, 0xf5, 0x82, 0xe4, 0x34, 0x02,
0xf5, 0x83, 0xe0, 0x90, 0xff, 0x5c, 0xf0, 0xef, 0xc3, 0x13, 0xff, 0xe5, 0x0d, 0x24, 0x1a, 0xf5,
0x82, 0xe4, 0x35, 0x0c, 0xf5, 0x83, 0xe5, 0x82, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83,
0xe4, 0x93, 0x90, 0xff, 0x55, 0xf0, 0x22, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xef, 0x75, 0xf0, 0x0a,
0xa4, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0xff, 0xa8, 0x3f, 0x08, 0x08,
0xe6, 0xfa, 0x08, 0xe6, 0xf5, 0x82, 0x8a, 0x83, 0x22, 0x74, 0x28, 0x93, 0x90, 0xff, 0x55, 0xf0,
0x90, 0x01, 0xf0, 0xe0, 0x90, 0xff, 0x54, 0xf0, 0x90, 0x01, 0xf1, 0xe0, 0x90, 0xff, 0x5c, 0xf0,
0x90, 0xff, 0x48, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x94, 0x07, 0xee, 0x94, 0x00, 0x22, 0x75, 0x91,
0xc3, 0xe4, 0xf5, 0x91, 0xe5, 0x89, 0x22, 0xfd, 0x7c, 0x00, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0xc3,
0x9d, 0xff, 0xea, 0x9c, 0xfe, 0xef, 0x78, 0x03, 0x22, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22,
0xad, 0x8e, 0xac, 0x8f, 0x75, 0x8a, 0xa0, 0xe4, 0x90, 0x00, 0xc0, 0x22, 0x90, 0xff, 0x52, 0xe0,
0xfe, 0xa3, 0xe0, 0xa6, 0x06, 0x08, 0xf6, 0x90, 0xff, 0x5a, 0xe0, 0xfe, 0xa3, 0xe0, 0x22, 0xe5,
0x27, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0xd3,
0xe5, 0x2a, 0x94, 0x00, 0xe5, 0x29, 0x64, 0x80, 0x94, 0x80, 0x22, 0x90, 0xff, 0x52, 0xe0, 0xfa,
0xa3, 0xe0, 0xc3, 0x9f, 0xea, 0x9e, 0x22, 0x90, 0xff, 0x5f, 0xf0, 0xed, 0x2b, 0xff, 0xec, 0x3a,
0xfe, 0xef, 0x78, 0x03, 0x22, 0x7f, 0xb4, 0x7b, 0x01, 0x7a, 0x02, 0x79, 0x03, 0x02, 0x10, 0x98,
0x90, 0xff, 0x5e, 0xf0, 0x90, 0xff, 0x56, 0xe0, 0xff, 0xa3, 0xe0, 0xd3, 0x9f, 0x22, 0x75, 0x91,
0xc1, 0xe4, 0xf5, 0x91, 0xe5, 0x89, 0x22, 0x78, 0x84, 0xe2, 0xfc, 0x08, 0xe2, 0x22, 0x74, 0xb7,
0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x26, 0x22, 0xe5, 0x27,
0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0xd3, 0x74,
0x05, 0x93, 0x9f, 0x74, 0x04, 0x93, 0x9e, 0x22, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x0b, 0xf5, 0x82,
0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0x90, 0xff, 0x43, 0x74, 0x9f, 0xf0, 0x22, 0x78, 0x83, 0xe2,
0x90, 0xff, 0x40, 0xf0, 0x22, 0xe5, 0x0d, 0x24, 0x2b, 0xff, 0xe4, 0x35, 0x0c, 0xa9, 0x07, 0x22,
0xef, 0x24, 0x01, 0xff, 0xee, 0x33, 0xfe, 0xef, 0x78, 0x07, 0x22, 0xe5, 0x22, 0xc3, 0x78, 0x65,
0x96, 0x22, 0xe0, 0xfc, 0xa3, 0xe0, 0xc3, 0x9f, 0x22, 0x8f, 0x23, 0x12, 0x05, 0x40, 0xe2, 0xfb,
0x12, 0x00, 0x60, 0x12, 0x04, 0x02, 0x12, 0x0d, 0x1a, 0x8e, 0x2f, 0x8f, 0x30, 0xeb, 0x70, 0x5f,
0x75, 0x24, 0x01, 0x12, 0x05, 0x6f, 0xe4, 0xf5, 0x29, 0xf5, 0x2a, 0x78, 0x61, 0xe2, 0xfe, 0x08,
0xe2, 0xff, 0x78, 0x60, 0x12, 0x02, 0xc1, 0x78, 0x65, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x78, 0x64,
0x12, 0x04, 0x76, 0xc3, 0x74, 0x09, 0x93, 0x94, 0x00, 0x50, 0x05, 0x12, 0x05, 0x7b, 0x80, 0x04,
0xae, 0x27, 0xaf, 0x28, 0x8e, 0x2d, 0x8f, 0x2e, 0x12, 0x00, 0x60, 0x74, 0x09, 0x93, 0xfc, 0x74,
0x0a, 0x12, 0x02, 0x7d, 0x40, 0x06, 0xae, 0x2d, 0xaf, 0x2e, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x01,
0x8e, 0x27, 0x8f, 0x28, 0x78, 0x69, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x78, 0x68, 0x80, 0x76, 0x78,
0x67, 0xe6, 0x14, 0x6b, 0x70, 0x7a, 0xf5, 0x24, 0x12, 0x05, 0x6f, 0x12, 0x00, 0x60, 0x74, 0x03,
0x93, 0xf5, 0x29, 0x74, 0x04, 0x93, 0xf5, 0x2a, 0x12, 0x00, 0xec, 0x12, 0x02, 0xb9, 0xeb, 0x25,
0xe0, 0x25, 0xe0, 0x24, 0x5d, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x5c, 0x12,
0x04, 0x75, 0xc3, 0x74, 0x0b, 0x93, 0x94, 0x00, 0x50, 0x05, 0x12, 0x05, 0x7b, 0x80, 0x04, 0xae,
0x27, 0xaf, 0x28, 0x8e, 0x2d, 0x8f, 0x2e, 0x12, 0x00, 0x60, 0x74, 0x0b, 0x93, 0xfc, 0x74, 0x0c,
0x12, 0x02, 0x7d, 0x40, 0x06, 0xae, 0x2d, 0xaf, 0x2e, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x01, 0x8e,
0x27, 0x8f, 0x28, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x59, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0,
0x25, 0xe0, 0x24, 0x58, 0xf8, 0xe2, 0x2f, 0xf5, 0x2c, 0x18, 0xe2, 0x3e, 0xf5, 0x2b, 0x80, 0x7d,
0xeb, 0xfd, 0x7c, 0x00, 0xae, 0x2f, 0xaf, 0x30, 0x12, 0x0d, 0x08, 0xac, 0x06, 0xad, 0x07, 0xe5,
0x2f, 0xc3, 0x13, 0xfe, 0xe5, 0x30, 0x13, 0x2d, 0xf5, 0x2a, 0xec, 0x3e, 0xf5, 0x29, 0xeb, 0x25,
0xe0, 0x25, 0xe0, 0x24, 0x5d, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x5c, 0x12,
0x02, 0xc0, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x65, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, 0x25,
0xe0, 0x24, 0x64, 0x12, 0x04, 0x75, 0xd3, 0xe5, 0x26, 0x95, 0x28, 0xe5, 0x27, 0x64, 0x80, 0xf8,
0xe5, 0x25, 0x64, 0x80, 0x98, 0x40, 0x11, 0xe4, 0xf5, 0x24, 0x85, 0x27, 0x2b, 0x85, 0x28, 0x2c,
0x85, 0x25, 0x27, 0x85, 0x26, 0x28, 0x80, 0x0f, 0x75, 0x24, 0x01, 0x85, 0x25, 0x2b, 0x85, 0x26,
0x2c, 0x85, 0x27, 0x27, 0x85, 0x28, 0x28, 0x12, 0x00, 0xec, 0x12, 0x02, 0xb9, 0xc3, 0xe5, 0x26,
0x95, 0x2c, 0xf5, 0x26, 0xe5, 0x25, 0x95, 0x2b, 0xf5, 0x25, 0xc3, 0x64, 0x80, 0x94, 0x80, 0x50,
0x05, 0xe4, 0xf5, 0x25, 0xf5, 0x26, 0xc3, 0xe5, 0x28, 0x95, 0x2c, 0xf5, 0x28, 0xe5, 0x27, 0x95,
0x2b, 0xf5, 0x27, 0xc3, 0x64, 0x80, 0x94, 0x80, 0x50, 0x05, 0xe4, 0xf5, 0x27, 0xf5, 0x28, 0x85,
0x27, 0x2b, 0x85, 0x28, 0x2c, 0xae, 0x2b, 0xaf, 0x2c, 0x12, 0x03, 0xd3, 0xe4, 0x7b, 0x80, 0xfa,
0xf9, 0xf8, 0x12, 0x01, 0x2b, 0xae, 0x2f, 0xaf, 0x30, 0x12, 0x04, 0x86, 0xc0, 0x06, 0xc0, 0x07,
0xe5, 0x26, 0x25, 0x28, 0xcf, 0xe5, 0x25, 0x35, 0x27, 0xcf, 0x24, 0x01, 0xcf, 0x34, 0x00, 0xab,
0x07, 0xfa, 0x33, 0x95, 0xe0, 0xf9, 0xf8, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x0f, 0x42, 0xef, 0x12,
0x05, 0xe7, 0xe4, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0xe4, 0x7b, 0x80, 0xfa, 0xf9, 0xf8, 0x12, 0x0f,
0x42, 0x8e, 0x2b, 0x8f, 0x2c, 0xe5, 0x24, 0x60, 0x0e, 0xe5, 0x2a, 0x25, 0x2c, 0xf5, 0x2c, 0xe5,
0x29, 0x35, 0x2b, 0xf5, 0x2b, 0x80, 0x0d, 0xc3, 0xe5, 0x2a, 0x95, 0x2c, 0xf5, 0x2c, 0xe5, 0x29,
0x95, 0x2b, 0xf5, 0x2b, 0xe5, 0x23, 0x12, 0x05, 0x17, 0xf8, 0xe5, 0x2b, 0xf2, 0x08, 0xe5, 0x2c,
0xf2, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, 0x1e, 0x8d, 0x1f, 0x90, 0x01, 0xfa, 0xe0, 0xf5, 0x21,
0xe4, 0xf5, 0x22, 0x85, 0x20, 0x20, 0xe5, 0x1f, 0x60, 0x04, 0x90, 0x00, 0xcb, 0xf0, 0x7d, 0x01,
0x7f, 0x12, 0x12, 0x32, 0xcc, 0x75, 0x23, 0x01, 0x75, 0x24, 0x00, 0x78, 0x73, 0xe6, 0xff, 0x70,
0x0b, 0x74, 0x20, 0x25, 0x24, 0xf5, 0x24, 0xe4, 0x35, 0x23, 0xf5, 0x23, 0x74, 0x00, 0x2f, 0xf9,
0xe4, 0x34, 0x01, 0xfa, 0x7b, 0x01, 0xa8, 0x24, 0xac, 0x23, 0x7d, 0x01, 0x7e, 0x00, 0x7f, 0x20,
0x12, 0x0c, 0x68, 0x7e, 0x00, 0x7f, 0x0b, 0x7d, 0xff, 0xe5, 0x24, 0x24, 0x09, 0xfb, 0xe4, 0x35,
0x23, 0xfa, 0xa9, 0x03, 0x7b, 0x01, 0x12, 0x10, 0x98, 0x05, 0x24, 0xe5, 0x24, 0xae, 0x23, 0x70,
0x02, 0x05, 0x23, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x12, 0x2b, 0x91, 0x90, 0x00, 0x0a,
0x12, 0x2b, 0x2a, 0xff, 0x90, 0x00, 0x04, 0x12, 0x0c, 0xa7, 0x2f, 0xf5, 0x22, 0x90, 0x00, 0x05,
0x12, 0x0c, 0xa7, 0xb4, 0x04, 0x09, 0x12, 0x2b, 0x58, 0x70, 0x04, 0x90, 0x00, 0xca, 0xf0, 0x90,
0x00, 0xca, 0xe0, 0x60, 0x4b, 0x14, 0xf0, 0xe0, 0xff, 0x7e, 0x04, 0x60, 0x02, 0x7e, 0x08, 0x12,
0x2b, 0x72, 0x90, 0x00, 0x05, 0xee, 0x12, 0x0c, 0xe6, 0xef, 0x60, 0x08, 0x12, 0x2b, 0x9b, 0xff,
0xae, 0xf0, 0x80, 0x10, 0x90, 0x00, 0xcb, 0xe0, 0xff, 0xb4, 0x05, 0x02, 0x80, 0x02, 0x7f, 0x00,
0xef, 0x7f, 0x00, 0xfe, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x27, 0xc4, 0x54, 0xf0, 0xfe, 0x12, 0x2b,
0x9b, 0xfd, 0xe5, 0xf0, 0x54, 0x0f, 0xfc, 0xe4, 0x2d, 0xff, 0xee, 0x3c, 0x8f, 0xf0, 0x80, 0x60,
0x12, 0x2b, 0x27, 0x70, 0x09, 0x12, 0x2b, 0x58, 0x70, 0x04, 0xe5, 0x1f, 0x60, 0x57, 0x12, 0x2b,
0x79, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x27, 0x60, 0x17, 0xc4, 0x54, 0xf0, 0xfe, 0x12, 0x0d, 0xbb,
0x24, 0x00, 0xff, 0xee, 0x35, 0xf0, 0xfe, 0x12, 0x2a, 0xec, 0x12, 0x2b, 0x5e, 0x12, 0x0e, 0x6b,
0x12, 0x2b, 0x52, 0x60, 0x35, 0xc4, 0x54, 0xf0, 0xfe, 0x90, 0x00, 0x06, 0x12, 0x0d, 0xe6, 0x24,
0x00, 0xff, 0xee, 0x35, 0xf0, 0xfe, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x72, 0x90, 0x00, 0x08, 0x12,
0x0d, 0xe6, 0x24, 0x00, 0xff, 0xe5, 0xf0, 0x34, 0x10, 0xfe, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x5e,
0x12, 0x0e, 0x6b, 0x80, 0x05, 0xe4, 0x90, 0x00, 0xcb, 0xf0, 0x90, 0x01, 0xfe, 0xe0, 0xd3, 0x94,
0xf0, 0x40, 0x70, 0x12, 0x2b, 0x91, 0x12, 0x2b, 0x79, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x72, 0x12,
0x0d, 0xbb, 0xff, 0xae, 0xf0, 0x12, 0x2a, 0xec, 0x90, 0x00, 0x06, 0x12, 0x2b, 0x05, 0x12, 0x2b,
0x72, 0x90, 0x00, 0x08, 0x12, 0x2b, 0x0b, 0x90, 0x01, 0x40, 0x74, 0x40, 0xf0, 0x90, 0x01, 0x60,
0x74, 0x60, 0xf0, 0x75, 0x2b, 0x01, 0x75, 0x2c, 0x41, 0x12, 0x2b, 0xa4, 0xaf, 0x28, 0x12, 0x39,
0xc9, 0xe5, 0x2c, 0xfd, 0x24, 0x02, 0xf5, 0x2c, 0xe5, 0x2b, 0xfc, 0x34, 0x00, 0xf5, 0x2b, 0x8d,
0x82, 0x8c, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xaf, 0x28, 0x12, 0x00, 0x12, 0xef, 0xd3, 0x94,
0x1c, 0x40, 0x06, 0x7e, 0x0f, 0x7f, 0xff, 0x80, 0x05, 0xaf, 0x28, 0x12, 0x39, 0x97, 0x12, 0x2b,
0x33, 0x40, 0xc9, 0x12, 0x2b, 0xa4, 0xaf, 0x28, 0x12, 0x39, 0x97, 0x12, 0x2b, 0x33, 0x40, 0xf6,
0x78, 0x73, 0xe6, 0x7f, 0x00, 0x70, 0x02, 0x7f, 0x20, 0x78, 0x73, 0xa6, 0x07, 0xe5, 0x21, 0x20,
0xe7, 0x2a, 0x30, 0xe6, 0x0a, 0x12, 0x2b, 0x27, 0x70, 0x22, 0x12, 0x2b, 0x58, 0x70, 0x1d, 0xe5,
0x21, 0x30, 0xe5, 0x0f, 0x12, 0x2b, 0x52, 0xff, 0x90, 0x00, 0x05, 0x12, 0x0c, 0xa7, 0x4f, 0x54,
0x84, 0x70, 0x09, 0xe5, 0x21, 0x30, 0xe4, 0x0c, 0xe5, 0x1f, 0x60, 0x08, 0x90, 0x01, 0xed, 0xe0,
0xff, 0x12, 0x31, 0x5d, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, 0x1e, 0x8d, 0x1f, 0xe4, 0xf5, 0x22,
0x90, 0x00, 0x05, 0x12, 0x0c, 0xa7, 0xf5, 0x23, 0x90, 0x00, 0x0b, 0x12, 0x0c, 0xa7, 0x60, 0x08,
0xe4, 0x78, 0x8a, 0xf2, 0x90, 0x00, 0xbf, 0xf0, 0xe5, 0x23, 0xb4, 0x80, 0x29, 0x78, 0x8a, 0x74,
0xff, 0xf2, 0x12, 0x34, 0xe0, 0x90, 0x00, 0xb9, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x34,
0xf1, 0x90, 0x00, 0xbb, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3,
0xe0, 0x04, 0xf0, 0x02, 0x1c, 0xa9, 0xe5, 0x23, 0x64, 0x08, 0x60, 0x03, 0x02, 0x1c, 0x56, 0x12,
0x34, 0xe0, 0xc3, 0x90, 0x00, 0xba, 0xe0, 0x90, 0x00, 0xb9, 0x12, 0x1c, 0xce, 0x8e, 0x24, 0x8f,
0x25, 0x12, 0x34, 0xeb, 0xc3, 0x90, 0x00, 0xbc, 0xe0, 0x90, 0x00, 0xbb, 0x12, 0x1c, 0xce, 0x12,
0x34, 0xd9, 0x74, 0x01, 0x93, 0xfc, 0x74, 0x02, 0x12, 0x34, 0xf9, 0x40, 0x12, 0x90, 0x01, 0xec,
0xe0, 0x30, 0xe0, 0x0b, 0x78, 0x8a, 0xe2, 0x54, 0xfe, 0xf2, 0xe4, 0x90, 0x00, 0xbf, 0xf0, 0xe5,
0x25, 0x2f, 0xfd, 0xe5, 0x24, 0x3e, 0xfc, 0x12, 0x34, 0xd9, 0x74, 0x05, 0x93, 0xfb, 0xd3, 0xed,
0x9b, 0xec, 0x94, 0x00, 0x40, 0x0b, 0x78, 0x8a, 0xe2, 0x54, 0xfc, 0xf2, 0xe4, 0x90, 0x00, 0xbf,
0xf0, 0x12, 0x34, 0xd9, 0x74, 0x03, 0x93, 0xfc, 0x74, 0x04, 0x12, 0x34, 0xf9, 0x40, 0x13, 0x78,
0x8a, 0xe2, 0x20, 0xe1, 0x04, 0xe5, 0x1f, 0x60, 0x09, 0x75, 0x22, 0x0c, 0xe4, 0x78, 0x8a, 0xf2,
0xf5, 0x1f, 0x78, 0x8a, 0xe2, 0x54, 0x3c, 0x70, 0x03, 0x02, 0x1c, 0xa9, 0x12, 0x34, 0xd9, 0x74,
0x06, 0x93, 0xfd, 0x7c, 0x00, 0xd3, 0xe5, 0x25, 0x9d, 0xe5, 0x24, 0x9c, 0x50, 0x09, 0xef, 0x9d,
0xee, 0x9c, 0x50, 0x03, 0x02, 0x1c, 0xa9, 0xd3, 0xef, 0x95, 0x25, 0xee, 0x95, 0x24, 0x40, 0x17,
0x12, 0x34, 0xeb, 0xd3, 0x90, 0x00, 0xbc, 0xe0, 0x9f, 0x90, 0x00, 0xbb, 0xe0, 0x95, 0xf0, 0x7f,
0x02, 0x40, 0x02, 0x7f, 0x01, 0x80, 0x15, 0x12, 0x34, 0xe0, 0xd3, 0x90, 0x00, 0xba, 0xe0, 0x9f,
0x90, 0x00, 0xb9, 0xe0, 0x95, 0xf0, 0x7f, 0x04, 0x40, 0x02, 0x7f, 0x03, 0x8f, 0x22, 0x78, 0x8a,
0xe2, 0x54, 0xc3, 0xf2, 0x80, 0x53, 0xe5, 0x23, 0xb4, 0x04, 0x09, 0xe4, 0x90, 0x00, 0xbd, 0xf0,
0xa3, 0xf0, 0x80, 0x45, 0x12, 0x34, 0xd9, 0x74, 0x01, 0x93, 0xfe, 0x74, 0x02, 0x93, 0xff, 0xd3,
0x90, 0x00, 0xbe, 0xe0, 0x9f, 0x90, 0x00, 0xbd, 0xe0, 0x9e, 0x50, 0x07, 0x90, 0x01, 0xec, 0xe0,
0x20, 0xe0, 0x26, 0x78, 0x8a, 0xe2, 0xff, 0x30, 0xe0, 0x1a, 0x90, 0x00, 0xbf, 0xe0, 0xfe, 0xd3,
0x94, 0x02, 0x50, 0x0a, 0xee, 0x7e, 0x0b, 0xb4, 0x01, 0x02, 0x7e, 0x05, 0x8e, 0x22, 0xef, 0x54,
0xfe, 0x78, 0x8a, 0xf2, 0xe4, 0x90, 0x00, 0xbf, 0xf0, 0xc3, 0x90, 0x00, 0xbd, 0xe0, 0x94, 0xff,
0x50, 0x13, 0x12, 0x34, 0xd9, 0xe4, 0x93, 0xff, 0x90, 0x00, 0xbe, 0xe0, 0x2f, 0xf0, 0x90, 0x00,
0xbd, 0xe0, 0x34, 0x00, 0xf0, 0xe5, 0x1f, 0xaf, 0x1f, 0x70, 0x02, 0xaf, 0x22, 0x22, 0x9f, 0xff,
0xe0, 0x95, 0xf0, 0xfe, 0x12, 0x39, 0xa3, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, 0x1e, 0x43, 0xad,
0x04, 0x90, 0xff, 0x40, 0xe0, 0x20, 0xe0, 0xf9, 0x43, 0x95, 0x80, 0x90, 0xff, 0x41, 0x74, 0x37,
0xf0, 0x90, 0xff, 0x49, 0x74, 0x0d, 0xf0, 0xe4, 0xf5, 0x25, 0xf5, 0x25, 0x12, 0x33, 0x70, 0xe5,
0x25, 0xc3, 0x9f, 0x50, 0x22, 0xe9, 0x24, 0x0c, 0xf9, 0xe4, 0x3a, 0x12, 0x33, 0x61, 0xe4, 0xfd,
0x12, 0x34, 0xaa, 0x12, 0x33, 0x57, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0x12, 0x33, 0x57, 0xe4, 0xfd,
0x12, 0x32, 0xcc, 0x05, 0x25, 0x80, 0xd5, 0x90, 0xff, 0x4a, 0xe4, 0xf0, 0x90, 0xff, 0x50, 0x74,
0x0f, 0xf0, 0x90, 0xff, 0x58, 0xe4, 0xf0, 0x90, 0xff, 0x40, 0x74, 0x08, 0xf0, 0x90, 0xff, 0x43,
0x74, 0x9f, 0xf0, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x12, 0x0c, 0x8e, 0x90, 0xff, 0x48, 0xf0,
0x90, 0x00, 0x01, 0x12, 0x0c, 0xa7, 0x90, 0xff, 0x42, 0xf0, 0x90, 0x00, 0x02, 0x12, 0x0c, 0xa7,
0x90, 0xff, 0x55, 0xf0, 0x90, 0x00, 0x03, 0x12, 0x0c, 0xa7, 0x90, 0xff, 0x54, 0xf0, 0x90, 0xff,
0x5c, 0xe4, 0xf0, 0xf5, 0x25, 0x12, 0x33, 0x70, 0xe5, 0x25, 0xc3, 0x9f, 0x50, 0x5b, 0xe4, 0xf5,
0x26, 0x75, 0x27, 0x64, 0x90, 0xff, 0x50, 0xe0, 0x20, 0xe7, 0x03, 0x43, 0x26, 0x01, 0xe5, 0x26,
0x64, 0x01, 0x60, 0x03, 0xd5, 0x27, 0xed, 0x12, 0x33, 0x7e, 0x12, 0x33, 0x57, 0x7d, 0x06, 0x12,
0x30, 0xb1, 0x90, 0xff, 0x40, 0x74, 0x29, 0xf0, 0x90, 0xff, 0x40, 0xe0, 0x20, 0xe0, 0xf9, 0x12,
0x33, 0x57, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0x90, 0xff, 0x52, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xab,
0x1f, 0xe5, 0x21, 0xf9, 0x24, 0x02, 0xf5, 0x21, 0xe5, 0x20, 0xfa, 0x34, 0x00, 0xf5, 0x20, 0xee,
0x8f, 0xf0, 0x12, 0x0e, 0x6b, 0x05, 0x25, 0x80, 0x9c, 0xe4, 0xf5, 0x25, 0x90, 0xff, 0x54, 0xf0,
0x75, 0x28, 0x01, 0x12, 0x33, 0x87, 0x74, 0xff, 0x12, 0x33, 0x54, 0x7d, 0x07, 0x12, 0x30, 0xb1,
0x90, 0xff, 0x55, 0x74, 0x64, 0xf0, 0xe4, 0xf5, 0x26, 0xf5, 0x27, 0x90, 0xff, 0x50, 0xe0, 0x30,
0xe7, 0x10, 0x05, 0x27, 0xe5, 0x27, 0x70, 0x02, 0x05, 0x26, 0xb4, 0xe8, 0xee, 0xe5, 0x26, 0xb4,
0x03, 0xe9, 0xe5, 0x28, 0x24, 0x02, 0x90, 0xff, 0x55, 0xf0, 0xe4, 0xf5, 0x26, 0xf5, 0x27, 0x00,
0x05, 0x27, 0xe5, 0x27, 0x70, 0x02, 0x05, 0x26, 0xb4, 0xe8, 0xf4, 0xe5, 0x26, 0xb4, 0x03, 0xef,
0xe4, 0xf5, 0x29, 0xf5, 0x26, 0xf5, 0x27, 0x90, 0xff, 0x50, 0xe0, 0x30, 0xe7, 0x03, 0x00, 0x80,
0x02, 0x05, 0x29, 0x05, 0x27, 0xe5, 0x27, 0x70, 0x02, 0x05, 0x26, 0x64, 0x64, 0x45, 0x26, 0x70,
0xe6, 0xe5, 0x29, 0xd3, 0x94, 0x28, 0x50, 0x0c, 0x12, 0x33, 0x7e, 0x05, 0x28, 0xe5, 0x28, 0xc3,
0x94, 0x64, 0x40, 0xae, 0x12, 0x33, 0x87, 0xe5, 0x28, 0x12, 0x33, 0x54, 0x7d, 0x08, 0x12, 0x30,
0xb1, 0x12, 0x33, 0x7e, 0x12, 0x33, 0x70, 0x05, 0x25, 0xe5, 0x25, 0xc3, 0x9f, 0x50, 0x03, 0x02,
0x1d, 0xe0, 0x90, 0xff, 0x50, 0xe4, 0xf0, 0xff, 0x22, 0xe4, 0x78, 0x62, 0xf6, 0x18, 0xe6, 0x14,
0x70, 0x03, 0x02, 0x1f, 0x69, 0x14, 0x70, 0x03, 0x02, 0x1f, 0xda, 0x24, 0x02, 0x60, 0x03, 0x02,
0x1f, 0xfc, 0x12, 0x14, 0xd2, 0xe4, 0x93, 0x78, 0x65, 0xf6, 0x78, 0x60, 0xe6, 0x30, 0xe0, 0x08,
0x75, 0x23, 0x05, 0x75, 0x24, 0x01, 0x80, 0x06, 0x75, 0x23, 0x08, 0xe4, 0xf5, 0x24, 0xe4, 0xf5,
0x22, 0x12, 0x16, 0xbb, 0x50, 0x3f, 0x12, 0x16, 0x57, 0x25, 0x22, 0x12, 0x14, 0xe4, 0xf5, 0x25,
0xe5, 0x22, 0x54, 0x01, 0xfd, 0xaf, 0x25, 0x12, 0x34, 0xaa, 0xad, 0x24, 0xaf, 0x25, 0x12, 0x32,
0xcc, 0xad, 0x23, 0xaf, 0x25, 0x12, 0x30, 0xb1, 0x78, 0x60, 0xe6, 0xb4, 0x03, 0x13, 0xe5, 0x22,
0x30, 0xe0, 0x0e, 0xe4, 0xfd, 0xaf, 0x25, 0x12, 0x32, 0xcc, 0x7d, 0x08, 0xaf, 0x25, 0x12, 0x30,
0xb1, 0x05, 0x22, 0x80, 0xbc, 0x78, 0x5d, 0xe6, 0xf5, 0x25, 0x75, 0x26, 0x10, 0x76, 0x40, 0x7e,
0x00, 0x7f, 0x12, 0x7d, 0x10, 0x7b, 0x01, 0x7a, 0x02, 0x79, 0xb7, 0x12, 0x10, 0x98, 0xe5, 0x26,
0xd3, 0x94, 0x01, 0x40, 0x3c, 0x12, 0x20, 0x01, 0x12, 0x16, 0xbb, 0x50, 0x2c, 0x12, 0x14, 0xd2,
0x74, 0x02, 0x93, 0x75, 0xf0, 0xa3, 0xa4, 0xff, 0xae, 0xf0, 0x12, 0x14, 0xec, 0x12, 0x16, 0xc2,
0xec, 0x9e, 0x50, 0x08, 0x12, 0x16, 0x5e, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x12, 0x16, 0x5e, 0xc3,
0x13, 0xfe, 0xef, 0x4e, 0xf0, 0x05, 0x22, 0x80, 0xcf, 0xe5, 0x26, 0xc3, 0x13, 0xf5, 0x26, 0x80,
0xbd, 0x78, 0x5d, 0xa6, 0x25, 0x78, 0x61, 0x76, 0x01, 0x12, 0x14, 0xd2, 0x74, 0x05, 0x93, 0x25,
0xe0, 0xf5, 0x25, 0x74, 0x04, 0x93, 0x33, 0xf5, 0x24, 0xe4, 0x78, 0x64, 0xf6, 0xfe, 0xfd, 0x12,
0x16, 0x35, 0x7e, 0x00, 0x7f, 0x24, 0x7d, 0x00, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x5f, 0x12, 0x10,
0x98, 0x75, 0x23, 0x04, 0x12, 0x31, 0x0b, 0x12, 0x20, 0x01, 0x12, 0x16, 0xbb, 0x50, 0x34, 0x12,
0x14, 0xec, 0xe0, 0xfe, 0xa3, 0xe0, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff,
0xe5, 0x22, 0x12, 0x15, 0x27, 0xee, 0x8f, 0xf0, 0x12, 0x0d, 0xa5, 0xe5, 0x22, 0x12, 0x15, 0x27,
0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x22, 0x12, 0x16, 0x88, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x05,
0x22, 0x80, 0xc7, 0xd5, 0x23, 0xc1, 0x78, 0x61, 0x76, 0x02, 0x12, 0x31, 0x0b, 0x12, 0x26, 0xc2,
0x78, 0x65, 0xe6, 0xfd, 0xe4, 0xff, 0x12, 0x2f, 0x6e, 0x78, 0x62, 0xe6, 0x30, 0xe1, 0x04, 0x78,
0x64, 0x76, 0x28, 0x78, 0x65, 0xe6, 0xfd, 0xe4, 0xff, 0x02, 0x21, 0x82, 0xe4, 0x78, 0x61, 0xf6,
0x22, 0x12, 0x26, 0xc2, 0x12, 0x31, 0x0b, 0xe4, 0xf5, 0x22, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89,
0x1e, 0xe4, 0xf5, 0x1f, 0xfe, 0x7f, 0x0c, 0xfd, 0x12, 0x10, 0x98, 0x7a, 0x00, 0x79, 0x02, 0x12,
0x04, 0x58, 0x7a, 0x00, 0x79, 0x31, 0x12, 0x04, 0x58, 0x78, 0x6d, 0xe6, 0x14, 0x60, 0x30, 0x04,
0x60, 0x03, 0x02, 0x21, 0x7b, 0xe4, 0x78, 0x6c, 0xf6, 0xff, 0x12, 0x39, 0xc4, 0x12, 0x1e, 0x89,
0x78, 0x62, 0xe6, 0x30, 0xe4, 0x03, 0x02, 0x21, 0x7f, 0x7e, 0x00, 0x7f, 0x5e, 0x7d, 0x00, 0x7b,
0xfe, 0x7a, 0x00, 0x79, 0x01, 0x12, 0x10, 0x98, 0x78, 0x6d, 0x76, 0x01, 0x02, 0x21, 0x73, 0x12,
0x1e, 0x89, 0x78, 0x62, 0xe6, 0xff, 0x30, 0xe4, 0x03, 0x02, 0x21, 0x7b, 0xef, 0x20, 0xe3, 0x03,
0x02, 0x21, 0x1f, 0x90, 0x00, 0x8b, 0xe0, 0x30, 0xe1, 0x39, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x21,
0x12, 0x39, 0xcd, 0xef, 0x60, 0x2d, 0x90, 0x00, 0x8b, 0x74, 0x02, 0xf0, 0x78, 0x06, 0x14, 0xf2,
0x78, 0x02, 0x14, 0xf2, 0x08, 0xe5, 0x21, 0xf2, 0x12, 0x00, 0x60, 0x74, 0x03, 0x93, 0xfc, 0x74,
0x04, 0x93, 0xfd, 0xec, 0xc3, 0x13, 0xfe, 0xed, 0x13, 0xff, 0xed, 0x2f, 0x78, 0x05, 0xf2, 0xec,
0x3e, 0x18, 0xf2, 0x90, 0x00, 0x8b, 0xe0, 0x30, 0xe0, 0x5b, 0x75, 0x25, 0x00, 0x75, 0x26, 0x00,
0x75, 0x27, 0x68, 0x75, 0x28, 0x00, 0x75, 0x29, 0x00, 0x75, 0x2a, 0x6a, 0x7b, 0xfe, 0x7a, 0x00,
0x79, 0x5f, 0x12, 0x29, 0x10, 0xe4, 0xf5, 0x20, 0xe5, 0x20, 0x12, 0x03, 0x72, 0xff, 0xe5, 0x20,
0x12, 0x05, 0x41, 0xef, 0xf2, 0xf4, 0x60, 0x1b, 0xe5, 0x20, 0x12, 0x05, 0xb8, 0xf9, 0xe4, 0xfa,
0x7b, 0xfe, 0xad, 0x20, 0x12, 0x39, 0x8b, 0xe5, 0x20, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x06, 0xf8,
0x74, 0x01, 0xf2, 0x05, 0x20, 0xe5, 0x20, 0xc3, 0x94, 0x02, 0x40, 0xcc, 0x12, 0x2a, 0x0e, 0x90,
0x00, 0x8b, 0x74, 0x01, 0xf0, 0x78, 0x62, 0xe6, 0x30, 0xe5, 0x04, 0x78, 0x6c, 0x76, 0x01, 0x90,
0x00, 0x8b, 0xe0, 0xf5, 0x1f, 0x78, 0x66, 0x76, 0x01, 0xe4, 0xf5, 0x20, 0xe5, 0x20, 0xc3, 0x94,
0x02, 0x50, 0x19, 0x90, 0x00, 0x8b, 0xe0, 0x30, 0xe0, 0x05, 0xaf, 0x20, 0x12, 0x39, 0xaf, 0x12,
0x30, 0x4c, 0x05, 0x20, 0x78, 0x66, 0x74, 0x2f, 0x26, 0xf6, 0x80, 0xe0, 0xa8, 0x1e, 0xac, 0x1d,
0xad, 0x1c, 0x12, 0x02, 0x9f, 0xe5, 0x1e, 0x24, 0x06, 0xf9, 0xe4, 0x35, 0x1d, 0xa8, 0x01, 0xfc,
0xad, 0x1c, 0x7a, 0x00, 0x79, 0x31, 0x12, 0x02, 0xa3, 0x78, 0x0d, 0xe2, 0x70, 0x11, 0x78, 0x3c,
0xe2, 0x70, 0x0c, 0x90, 0x00, 0x8b, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xe4, 0x78, 0x6d, 0xf6, 0xaf,
0x1f, 0x22, 0x8f, 0x27, 0x8d, 0x28, 0x78, 0x64, 0xe6, 0x60, 0x01, 0x16, 0x12, 0x15, 0x25, 0xe0,
0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x27, 0x12, 0x14, 0xee, 0x12, 0x16, 0xc2, 0xf5, 0x2a, 0xec, 0x9e,
0xf5, 0x29, 0x12, 0x16, 0x6e, 0xe0, 0xf5, 0x2b, 0xe4, 0xf5, 0x2c, 0x12, 0x16, 0x0f, 0x40, 0x06,
0xae, 0x29, 0xaf, 0x2a, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe5, 0x27, 0x25, 0xe0, 0x24, 0x5f,
0xf8, 0xee, 0xf2, 0x08, 0xef, 0xf2, 0x90, 0x36, 0x0b, 0xe4, 0x93, 0x60, 0x07, 0x78, 0x64, 0xe6,
0xf5, 0x2c, 0x80, 0x0f, 0x12, 0x16, 0x0f, 0x7f, 0x00, 0x40, 0x02, 0x7f, 0x01, 0xef, 0x78, 0x64,
0x56, 0xf5, 0x2c, 0xe5, 0x2c, 0x60, 0x03, 0x02, 0x22, 0x9e, 0xaf, 0x2a, 0xae, 0x29, 0x12, 0x39,
0xa3, 0x12, 0x14, 0xd2, 0xc3, 0x12, 0x16, 0x7f, 0x50, 0x0d, 0x12, 0x16, 0x10, 0x40, 0x04, 0x05,
0x2b, 0x80, 0x57, 0x15, 0x2b, 0x80, 0x53, 0x12, 0x15, 0xff, 0xe0, 0xff, 0x33, 0x95, 0xe0, 0xfe,
0xef, 0x25, 0x2a, 0xf5, 0x2a, 0xee, 0x35, 0x29, 0xf5, 0x29, 0xd3, 0xe5, 0x2a, 0x94, 0x78, 0x12,
0x16, 0x14, 0x40, 0x09, 0x12, 0x15, 0x25, 0xe4, 0x75, 0xf0, 0x01, 0x80, 0x1a, 0xe5, 0x2a, 0x24,
0x78, 0xe4, 0x35, 0x29, 0xc3, 0x64, 0x80, 0x94, 0x80, 0xe5, 0x27, 0x75, 0xf0, 0x0a, 0x50, 0x11,
0x12, 0x15, 0x2a, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x0d, 0xa5, 0x12, 0x15, 0xff, 0xe4, 0xf0, 0x80,
0x06, 0x12, 0x16, 0x04, 0xe5, 0x2a, 0xf0, 0xe4, 0xf5, 0x2b, 0x12, 0x14, 0xd2, 0x74, 0x01, 0x93,
0xff, 0xd3, 0x64, 0x80, 0xf8, 0xe5, 0x2b, 0x64, 0x80, 0x98, 0x50, 0x17, 0xef, 0x33, 0x95, 0xe0,
0xfe, 0xad, 0x2b, 0xed, 0x33, 0x95, 0xe0, 0xfc, 0xed, 0x2f, 0xec, 0x3e, 0xc3, 0x64, 0x80, 0x94,
0x80, 0x50, 0x15, 0xe4, 0xf5, 0x2b, 0xe5, 0x27, 0x12, 0x14, 0xee, 0xe0, 0xfe, 0xa3, 0xe0, 0xff,
0x12, 0x15, 0x25, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x16, 0x6e, 0xe5, 0x2b, 0xf0, 0x78, 0x64,
0xe6, 0x70, 0x3a, 0x12, 0x15, 0x25, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x27, 0x12, 0x16, 0x88,
0x12, 0x16, 0xc2, 0xff, 0xec, 0x9e, 0xfe, 0x12, 0x39, 0xa3, 0xaa, 0x06, 0xab, 0x07, 0x12, 0x14,
0xd2, 0x74, 0x04, 0x93, 0xfe, 0x74, 0x05, 0x93, 0xff, 0x7c, 0x00, 0x7d, 0x03, 0x12, 0x0d, 0x08,
0xd3, 0xeb, 0x9f, 0xea, 0x9e, 0x40, 0x06, 0x78, 0x62, 0xe6, 0x44, 0x10, 0xf6, 0x05, 0x27, 0x15,
0x28, 0xe5, 0x28, 0x60, 0x03, 0x02, 0x21, 0x8c, 0x22, 0x8e, 0x1c, 0x8f, 0x1d, 0xe4, 0x78, 0x61,
0xf6, 0x85, 0x1c, 0x0c, 0x85, 0x1d, 0x0d, 0xe5, 0x1d, 0x24, 0x2c, 0xff, 0xe4, 0x35, 0x1c, 0xfa,
0xa9, 0x07, 0x7b, 0xff, 0x78, 0x5d, 0x7c, 0x00, 0x7d, 0x00, 0x7e, 0x00, 0x7f, 0x04, 0x12, 0x0c,
0x68, 0x78, 0x84, 0x74, 0x01, 0xf2, 0x08, 0x74, 0xcc, 0xf2, 0x85, 0x1d, 0x82, 0x85, 0x1c, 0x83,
0xe4, 0x93, 0xff, 0x7e, 0x00, 0xe5, 0x1d, 0x24, 0x06, 0xfd, 0xe4, 0x35, 0x1c, 0xfa, 0xa9, 0x05,
0x7b, 0xff, 0x18, 0xe2, 0xfc, 0x08, 0xe2, 0xf8, 0x7d, 0x01, 0x12, 0x0c, 0x68, 0x90, 0x01, 0xa7,
0xe0, 0xff, 0x12, 0x34, 0x0d, 0x90, 0x00, 0xc1, 0xe0, 0x64, 0x80, 0x70, 0x04, 0xa3, 0xe0, 0x64,
0x75, 0x70, 0x44, 0xff, 0x85, 0x1d, 0x82, 0x85, 0x1c, 0x83, 0xe4, 0x93, 0xfe, 0xef, 0xc3, 0x9e,
0x50, 0x35, 0xe4, 0xf5, 0x1f, 0x12, 0x16, 0x57, 0xfd, 0x12, 0x14, 0xe3, 0xfe, 0xe5, 0x1f, 0x90,
0x39, 0xd0, 0x93, 0xfb, 0xee, 0x6b, 0x60, 0x0b, 0xe5, 0x1f, 0xc3, 0x94, 0x0f, 0x50, 0x04, 0x05,
0x1f, 0x80, 0xe2, 0xe5, 0x1f, 0x90, 0x39, 0xdf, 0x93, 0xfe, 0xed, 0x2f, 0xf5, 0x82, 0xe4, 0x3c,
0xf5, 0x83, 0xee, 0xf0, 0x0f, 0x80, 0xbd, 0x7e, 0x00, 0x7d, 0x00, 0x12, 0x16, 0x35, 0x12, 0x14,
0xd2, 0x74, 0x02, 0x93, 0xff, 0x7e, 0x00, 0x7c, 0x10, 0x7d, 0x00, 0x12, 0x10, 0x6b, 0xe4, 0x7b,
0xc8, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, 0x42, 0x90, 0x02, 0x00, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x78,
0x83, 0x74, 0x09, 0xf2, 0x78, 0x5f, 0xe6, 0xff, 0x20, 0xe3, 0x06, 0x78, 0x83, 0xe2, 0x44, 0x04,
0xf2, 0xef, 0x20, 0xe2, 0x06, 0x78, 0x83, 0xe2, 0x44, 0x20, 0xf2, 0xe4, 0x78, 0x63, 0xf6, 0x43,
0x95, 0x80, 0x78, 0x5f, 0xe6, 0x7f, 0x00, 0x30, 0xe1, 0x02, 0x7f, 0x40, 0xef, 0x44, 0x37, 0x90,
0xff, 0x41, 0xf0, 0x90, 0xff, 0x49, 0x74, 0x0d, 0xf0, 0x75, 0x1e, 0x11, 0xe5, 0x1e, 0xf4, 0x60,
0x0c, 0xe4, 0xfd, 0xaf, 0x1e, 0x12, 0x32, 0xcc, 0xe4, 0xfd, 0x12, 0x24, 0x30, 0x75, 0x1e, 0x16,
0xe5, 0x1e, 0xf4, 0x60, 0x0c, 0xe4, 0xfd, 0xaf, 0x1e, 0x12, 0x32, 0xcc, 0x7d, 0x01, 0x12, 0x24,
0x30, 0x78, 0x60, 0xe6, 0x7f, 0x08, 0x30, 0xe0, 0x02, 0x7f, 0x05, 0x78, 0x87, 0xef, 0xf2, 0x22,
0xaf, 0x1e, 0x12, 0x34, 0xaa, 0x7d, 0x08, 0xaf, 0x1e, 0x12, 0x30, 0xb1, 0x7d, 0x07, 0xaf, 0x1e,
0x12, 0x30, 0xb1, 0x22, 0x8f, 0x23, 0x12, 0x05, 0x40, 0xe2, 0xff, 0x70, 0x04, 0xf5, 0x24, 0x80,
0x18, 0x78, 0x67, 0xe6, 0xfe, 0x14, 0xb5, 0x07, 0x09, 0xee, 0x25, 0xe0, 0x24, 0xfa, 0xf5, 0x24,
0x80, 0x07, 0xef, 0x25, 0xe0, 0x24, 0xfe, 0xf5, 0x24, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x63, 0x12,
0x00, 0xf3, 0xe5, 0x24, 0x12, 0x02, 0xd8, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x68, 0x12, 0x02, 0xdc,
0xe4, 0xfc, 0xfd, 0x78, 0x4f, 0x12, 0x10, 0x34, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x65, 0x12, 0x00,
0xf3, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x62, 0x12, 0x02, 0xdc, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x6a,
0x12, 0x02, 0xdc, 0xe4, 0xfc, 0xfd, 0x78, 0x53, 0x12, 0x10, 0x34, 0x12, 0x00, 0x60, 0x74, 0x07,
0x93, 0xfe, 0x74, 0x08, 0x78, 0x53, 0x12, 0x04, 0x63, 0x12, 0x0e, 0xb7, 0xc0, 0x04, 0xc0, 0x05,
0xc0, 0x06, 0xc0, 0x07, 0x12, 0x00, 0x60, 0x78, 0x53, 0x12, 0x03, 0x05, 0x12, 0x0e, 0xb7, 0xd0,
0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x12, 0x01, 0xc3, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06,
0xc0, 0x07, 0x12, 0x00, 0x60, 0x74, 0x05, 0x93, 0xfe, 0x74, 0x06, 0x78, 0x4f, 0x12, 0x04, 0x63,
0x12, 0x01, 0x2b, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xc3, 0xef, 0x9b, 0xff, 0xee,
0x9a, 0xfe, 0xed, 0x99, 0xfd, 0xec, 0x98, 0xfc, 0x78, 0x57, 0x12, 0x10, 0x34, 0x78, 0x57, 0x12,
0x10, 0x0b, 0xec, 0x33, 0x50, 0x0b, 0x78, 0x4f, 0x12, 0x10, 0x40, 0x00, 0x00, 0x00, 0x01, 0x80,
0x5b, 0x12, 0x05, 0x63, 0x7b, 0x02, 0x12, 0x02, 0x36, 0x12, 0x0f, 0x42, 0x78, 0x57, 0x12, 0x10,
0x17, 0x12, 0x01, 0xc3, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x05, 0x63, 0x2f,
0xfb, 0xea, 0x3e, 0xfa, 0xe9, 0x3d, 0xf9, 0xe8, 0x3c, 0xf8, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05,
0xd0, 0x04, 0x12, 0x0f, 0x42, 0x78, 0x4f, 0x12, 0x10, 0x34, 0x12, 0x00, 0x60, 0x78, 0x4f, 0x12,
0x03, 0x05, 0xd3, 0x12, 0x0f, 0xd4, 0x40, 0x14, 0x12, 0x00, 0x60, 0x74, 0x02, 0x93, 0x24, 0xff,
0xff, 0x74, 0x01, 0x93, 0x12, 0x02, 0x2c, 0x78, 0x4f, 0x12, 0x10, 0x34, 0x78, 0x4f, 0x12, 0x10,
0x0b, 0xe5, 0x23, 0x12, 0x02, 0xac, 0x22, 0x8b, 0x1f, 0x8a, 0x20, 0x89, 0x21, 0x43, 0xad, 0x04,
0x43, 0x95, 0x80, 0x90, 0xff, 0x41, 0x74, 0x80, 0xf0, 0x90, 0xff, 0x49, 0x74, 0x0d, 0xf0, 0xa3,
0xe4, 0xf0, 0x90, 0xff, 0x42, 0x04, 0xf0, 0x90, 0xff, 0x55, 0x74, 0x7d, 0xf0, 0x90, 0xff, 0x54,
0xe4, 0xf0, 0x90, 0xff, 0x5c, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x10, 0xf0, 0xe4, 0xf5, 0x26, 0xf5,
0x27, 0xf5, 0x28, 0xf5, 0x29, 0xf5, 0x25, 0xe4, 0x12, 0x35, 0xaa, 0xf4, 0x60, 0x0d, 0xe4, 0xfd,
0x12, 0x32, 0xcc, 0x12, 0x35, 0xb2, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0x12, 0x35, 0x9c, 0xf4, 0x60,
0x0d, 0xe4, 0xfd, 0x12, 0x32, 0xcc, 0x12, 0x35, 0x9c, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0xe4, 0xff,
0x00, 0x0f, 0xbf, 0xc8, 0xfb, 0x74, 0x03, 0x12, 0x35, 0xaa, 0xf4, 0x60, 0x0d, 0xe4, 0xfd, 0x12,
0x34, 0xaa, 0x12, 0x35, 0xb2, 0x7d, 0x07, 0x12, 0x30, 0xb1, 0x12, 0x35, 0x9c, 0xf4, 0x60, 0x0d,
0x7d, 0x01, 0x12, 0x34, 0xaa, 0x12, 0x35, 0x9c, 0x7d, 0x07, 0x12, 0x30, 0xb1, 0x90, 0xff, 0x43,
0x74, 0x9f, 0xf0, 0x90, 0xff, 0x50, 0x74, 0x07, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x90, 0xff, 0x40,
0x74, 0x09, 0xf0, 0x75, 0x8a, 0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x90, 0xff, 0x43, 0xe0, 0x30,
0xe4, 0xf9, 0x90, 0xff, 0x43, 0x74, 0x9f, 0xf0, 0x90, 0xff, 0x52, 0xe0, 0xfe, 0xa3, 0xe0, 0x25,
0x27, 0xf5, 0x27, 0xee, 0x35, 0x26, 0xf5, 0x26, 0x90, 0xff, 0x5a, 0xe0, 0xfe, 0xa3, 0xe0, 0x25,
0x29, 0xf5, 0x29, 0xee, 0x35, 0x28, 0xf5, 0x28, 0x05, 0x25, 0xe5, 0x25, 0xc3, 0x94, 0x04, 0x50,
0x03, 0x02, 0x25, 0xc7, 0xe5, 0x27, 0xae, 0x26, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8,
0xf9, 0xff, 0xab, 0x22, 0xaa, 0x23, 0xa9, 0x24, 0xee, 0x8f, 0xf0, 0x12, 0x0e, 0x6b, 0xe5, 0x29,
0xae, 0x28, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xab, 0x22, 0xaa, 0x23,
0xa9, 0x24, 0x90, 0x00, 0x02, 0xee, 0x8f, 0xf0, 0x12, 0x0e, 0x8a, 0x12, 0x35, 0xb2, 0xf4, 0x60,
0x05, 0xe4, 0xfd, 0x12, 0x30, 0xb1, 0x12, 0x35, 0x9c, 0xf4, 0x60, 0x05, 0xe4, 0xfd, 0x12, 0x30,
0xb1, 0x22, 0xe4, 0xf5, 0x27, 0xe5, 0x27, 0xc3, 0x78, 0x65, 0x96, 0x50, 0x2b, 0x12, 0x16, 0x57,
0x25, 0x27, 0x12, 0x14, 0xe4, 0xf5, 0x28, 0x78, 0x60, 0xe6, 0x54, 0x01, 0xfd, 0xaf, 0x28, 0x12,
0x32, 0xcc, 0x78, 0x60, 0xe6, 0xb4, 0x03, 0x0c, 0xe5, 0x27, 0x30, 0xe0, 0x07, 0xe4, 0xfd, 0xaf,
0x28, 0x12, 0x32, 0xcc, 0x05, 0x27, 0x80, 0xcd, 0x90, 0xff, 0x4a, 0x74, 0x71, 0xf0, 0x90, 0xff,
0x50, 0x74, 0x0f, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x90, 0xff, 0x40, 0xe4, 0xf0, 0x12, 0x16, 0x96,
0x90, 0xff, 0x54, 0xe4, 0xf0, 0x90, 0xff, 0x5c, 0xf0, 0x78, 0x5e, 0xe6, 0x90, 0xff, 0x42, 0xf0,
0x90, 0xff, 0x55, 0x74, 0x28, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x02, 0xf0, 0x43, 0xad, 0x04, 0x12,
0x16, 0x9d, 0x90, 0xff, 0x43, 0xe0, 0x20, 0xe4, 0x1d, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x14,
0x84, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12, 0x16, 0x4e, 0x30, 0xe7, 0xe6, 0x12, 0x14, 0x84, 0x50,
0xe1, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0x12, 0x16, 0x96, 0xe4, 0x78, 0x86, 0xf2, 0x78, 0x5c, 0xf6,
0x18, 0x76, 0x01, 0x78, 0x65, 0xe6, 0xc3, 0x13, 0x78, 0x63, 0xf6, 0x78, 0x5e, 0xe6, 0x90, 0xff,
0x42, 0xf0, 0x18, 0xe6, 0x90, 0xff, 0x48, 0xf0, 0x78, 0x5f, 0xe6, 0x7f, 0x00, 0x20, 0xe4, 0x02,
0x7f, 0x01, 0x90, 0x02, 0x02, 0xef, 0xf0, 0x12, 0x15, 0x35, 0x08, 0x12, 0x14, 0xdb, 0xff, 0x7d,
0x06, 0x12, 0x30, 0xb1, 0x78, 0x5b, 0x12, 0x14, 0xdb, 0xff, 0x7d, 0x06, 0x12, 0x30, 0xb1, 0x78,
0x83, 0xe2, 0xff, 0x90, 0xff, 0x40, 0xf0, 0x78, 0x5f, 0xe6, 0x30, 0xe7, 0x3e, 0x43, 0xad, 0x04,
0xef, 0xf0, 0x90, 0xff, 0x43, 0xe0, 0x20, 0xe4, 0x1d, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x14,
0x84, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12, 0x16, 0x4e, 0x30, 0xe7, 0xe6, 0x12, 0x14, 0x84, 0x50,
0xe1, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0x7b, 0xff, 0x7a, 0x30, 0x79, 0xb1, 0x12, 0x27, 0xf2, 0x12,
0x15, 0xe4, 0xf0, 0x78, 0x63, 0xe6, 0x70, 0xca, 0x02, 0x31, 0x0b, 0x53, 0xad, 0xfb, 0x12, 0x16,
0x9d, 0x22, 0x15, 0x3f, 0x15, 0x3f, 0x15, 0x3f, 0xa8, 0x3f, 0xa6, 0x03, 0x08, 0xa6, 0x02, 0x08,
0xa6, 0x01, 0x15, 0x3f, 0x12, 0x16, 0x96, 0x78, 0x87, 0xe2, 0xa8, 0x3f, 0xf6, 0x12, 0x14, 0xd9,
0xff, 0xa8, 0x3f, 0xe6, 0xfd, 0x12, 0x15, 0x8e, 0x12, 0x10, 0x69, 0x78, 0x60, 0xe6, 0x64, 0x03,
0x78, 0x5b, 0x60, 0x0d, 0x12, 0x14, 0xdb, 0xff, 0xa8, 0x3f, 0xe6, 0xfd, 0x12, 0x15, 0x8e, 0x80,
0x08, 0x12, 0x14, 0xdb, 0x12, 0x15, 0x8b, 0x7d, 0x08, 0x12, 0x10, 0x69, 0x90, 0xff, 0x52, 0xe0,
0xfe, 0xa3, 0xe0, 0xff, 0x78, 0x5c, 0xe6, 0x12, 0x15, 0x7d, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x12,
0x15, 0xf7, 0xff, 0x18, 0xe6, 0x12, 0x15, 0x7d, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x02, 0x02,
0xe0, 0x60, 0x2e, 0x08, 0xe6, 0xff, 0x12, 0x14, 0xee, 0x12, 0x15, 0x77, 0x12, 0x29, 0x02, 0x12,
0x14, 0xd2, 0x12, 0x16, 0x7e, 0x40, 0x1a, 0x78, 0x5b, 0xe6, 0xff, 0x12, 0x14, 0xee, 0x12, 0x15,
0x77, 0x12, 0x29, 0x02, 0x12, 0x14, 0xd2, 0x12, 0x16, 0x7e, 0x40, 0x05, 0xe4, 0x90, 0x02, 0x02,
0xf0, 0x90, 0x02, 0x02, 0xe0, 0x70, 0x1b, 0x78, 0x5c, 0x06, 0x06, 0x18, 0x06, 0x06, 0x78, 0x63,
0x16, 0x78, 0x5f, 0xe6, 0x7f, 0x00, 0x20, 0xe4, 0x02, 0x7f, 0x01, 0x90, 0x02, 0x02, 0xef, 0xf0,
0x80, 0x05, 0xe4, 0x90, 0x02, 0x02, 0xf0, 0x78, 0x63, 0xe6, 0x70, 0x0a, 0x90, 0xff, 0x50, 0xf0,
0x90, 0xff, 0x58, 0xf0, 0x80, 0x35, 0x12, 0x15, 0x35, 0xa8, 0x3f, 0x76, 0x64, 0x90, 0xff, 0x58,
0xe0, 0xff, 0x90, 0xff, 0x50, 0xe0, 0x4f, 0x30, 0xe7, 0x06, 0xa8, 0x3f, 0x16, 0xe6, 0x70, 0xed,
0x12, 0x14, 0xd9, 0x12, 0x15, 0x8b, 0x7d, 0x06, 0x12, 0x10, 0x69, 0x78, 0x5b, 0x12, 0x14, 0xdb,
0x12, 0x15, 0x8b, 0x7d, 0x06, 0x12, 0x10, 0x69, 0x12, 0x16, 0x9d, 0xe5, 0x3f, 0x24, 0x04, 0xf5,
0x3f, 0x22, 0xe0, 0xfe, 0xa3, 0xe0, 0xc3, 0x9d, 0xff, 0xee, 0x9c, 0xfe, 0x12, 0x39, 0xa3, 0x22,
0x8b, 0x22, 0x8a, 0x23, 0x89, 0x24, 0x12, 0x2d, 0x79, 0x12, 0x2d, 0xfc, 0x12, 0x31, 0xac, 0x74,
0x55, 0x93, 0xf5, 0x2b, 0xe4, 0xf5, 0x2c, 0x12, 0x31, 0xef, 0x12, 0x0c, 0x8e, 0x70, 0x21, 0x12,
0x31, 0xac, 0x74, 0x74, 0x93, 0xf5, 0x2d, 0xc3, 0x64, 0x80, 0x94, 0x80, 0x7f, 0x00, 0x50, 0x02,
0x7f, 0x01, 0x12, 0x29, 0xd6, 0xee, 0x8f, 0xf0, 0x12, 0x0e, 0x1e, 0x75, 0x2c, 0x03, 0x80, 0x3a,
0x12, 0x31, 0xef, 0x12, 0x0c, 0x8e, 0xff, 0xe5, 0x2b, 0x14, 0x6f, 0x70, 0x2d, 0x12, 0x31, 0xac,
0x74, 0x75, 0x93, 0xf5, 0x2d, 0xc3, 0x64, 0x80, 0x94, 0x80, 0xe5, 0x2b, 0x50, 0x06, 0x25, 0xe0,
0x14, 0xff, 0x80, 0x05, 0x25, 0xe0, 0x24, 0xfe, 0xff, 0x12, 0x29, 0xd6, 0xee, 0x8f, 0xf0, 0x12,
0x0e, 0x1e, 0xe5, 0x2b, 0x25, 0xe0, 0x24, 0xfd, 0xf5, 0x2c, 0xe5, 0x2c, 0x60, 0x47, 0x24, 0xff,
0xff, 0xe4, 0x34, 0xff, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xab, 0x22, 0xaa, 0x23, 0xa9,
0x24, 0x8f, 0x82, 0xf5, 0x83, 0x12, 0x0d, 0xe6, 0xff, 0xae, 0xf0, 0x75, 0xf0, 0x02, 0xe5, 0x2c,
0xa4, 0xf5, 0x82, 0x85, 0xf0, 0x83, 0x12, 0x0d, 0xe6, 0x2f, 0xff, 0xee, 0x35, 0xf0, 0xfe, 0x12,
0x31, 0xac, 0xd3, 0x74, 0x77, 0x93, 0x9f, 0x74, 0x76, 0x93, 0x9e, 0x40, 0x08, 0x12, 0x31, 0xef,
0x74, 0xff, 0x12, 0x0c, 0xd4, 0x22, 0x8f, 0x2c, 0xaf, 0x2d, 0xef, 0x33, 0x95, 0xe0, 0xfe, 0x12,
0x39, 0xa3, 0xab, 0x22, 0xaa, 0x23, 0xa9, 0x24, 0x75, 0xf0, 0x02, 0xe5, 0x2c, 0xa4, 0xf5, 0x82,
0x85, 0xf0, 0x83, 0x12, 0x0d, 0xe6, 0xfd, 0xac, 0xf0, 0xcf, 0xcd, 0xcf, 0xce, 0xcc, 0xce, 0x12,
0x0d, 0x1a, 0x75, 0xf0, 0x02, 0xe5, 0x2c, 0xa4, 0xf5, 0x82, 0x85, 0xf0, 0x83, 0x22, 0xe4, 0xf5,
0x22, 0xf5, 0x23, 0xff, 0xfe, 0x78, 0x35, 0xe2, 0x25, 0xe0, 0xfd, 0x78, 0x06, 0xe2, 0x2d, 0xfd,
0x78, 0x0c, 0xe2, 0xc4, 0x54, 0xf0, 0x2d, 0xfd, 0x78, 0x3b, 0xe2, 0xfc, 0xc4, 0x33, 0x54, 0xe0,
0x2d, 0x24, 0xfe, 0x60, 0x25, 0x24, 0xf0, 0x60, 0x21, 0x14, 0x60, 0x26, 0x24, 0xf2, 0x60, 0x1a,
0x24, 0xfe, 0x60, 0x2e, 0x24, 0xf1, 0x60, 0x0c, 0x14, 0x60, 0x3b, 0x24, 0x02, 0x70, 0x6c, 0xe4,
0xfd, 0xff, 0x80, 0x22, 0x7d, 0x01, 0x7f, 0x01, 0x80, 0x0b, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01,
0x80, 0x59, 0xe4, 0xfd, 0xff, 0x12, 0x32, 0x86, 0x8e, 0x22, 0x8f, 0x23, 0xe4, 0xfd, 0x7f, 0x01,
0x80, 0x0f, 0x7d, 0x01, 0x7f, 0x01, 0x12, 0x32, 0x86, 0x8e, 0x22, 0x8f, 0x23, 0x7d, 0x01, 0xe4,
0xff, 0x12, 0x32, 0x86, 0x80, 0x35, 0x7d, 0x01, 0x7f, 0x01, 0x12, 0x32, 0x86, 0xc0, 0x06, 0xc0,
0x07, 0xe4, 0xfd, 0xff, 0x12, 0x32, 0x86, 0xd0, 0xe0, 0x2f, 0xf5, 0x23, 0xd0, 0xe0, 0x3e, 0xf5,
0x22, 0xe4, 0xfd, 0x7f, 0x01, 0x12, 0x32, 0x86, 0xc0, 0x06, 0xc0, 0x07, 0x7d, 0x01, 0xe4, 0xff,
0x12, 0x32, 0x86, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xd3, 0xe5, 0x23, 0x9f, 0xe5,
0x22, 0x9e, 0x40, 0x27, 0x78, 0x24, 0x7c, 0x00, 0x7d, 0x00, 0x12, 0x02, 0x9f, 0x78, 0x02, 0x7c,
0x00, 0x7d, 0xfe, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x31, 0x12, 0x02, 0xa5, 0x78, 0x31, 0x7c, 0x00,
0x7d, 0xfe, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x12, 0x02, 0xa5, 0x22, 0xab, 0x25, 0xe5, 0x27,
0xf9, 0x24, 0x02, 0xf5, 0x27, 0xe5, 0x26, 0xfa, 0x34, 0x00, 0xf5, 0x26, 0xee, 0x8f, 0xf0, 0x12,
0x0e, 0x6b, 0x90, 0x00, 0x02, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x12, 0x0d, 0xe6, 0xff, 0xae,
0xf0, 0xab, 0x25, 0xe5, 0x27, 0xf9, 0x24, 0x02, 0xf5, 0x27, 0xe5, 0x26, 0xfa, 0x34, 0x00, 0xf5,
0x26, 0xee, 0x8f, 0xf0, 0x02, 0x0e, 0x6b, 0x90, 0x00, 0x05, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e,
0x02, 0x0c, 0xa7, 0xe5, 0x2a, 0xfd, 0x24, 0x02, 0xf5, 0x2a, 0xe5, 0x29, 0xfc, 0x34, 0x00, 0xf5,
0x29, 0x8d, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x05, 0x28, 0xe5, 0x28, 0xc3, 0x94,
0x10, 0x22, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x90, 0x00, 0x0b, 0x02, 0x0c, 0xa7, 0xab, 0x25,
0xe5, 0x27, 0xf9, 0x24, 0x02, 0xf5, 0x27, 0xe5, 0x26, 0xfa, 0x34, 0x00, 0xf5, 0x26, 0xe4, 0xf5,
0xf0, 0x22, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x22, 0xe5, 0x1f, 0xfe, 0x7c, 0x00, 0xe4, 0x25,
0x22, 0xff, 0xec, 0x3e, 0xfe, 0x22, 0x75, 0x89, 0x80, 0x90, 0x00, 0xc3, 0xe0, 0xc3, 0x94, 0xff,
0x22, 0x75, 0x25, 0x01, 0x85, 0x23, 0x26, 0x85, 0x24, 0x27, 0x22, 0xab, 0x25, 0xaa, 0x26, 0xa9,
0x27, 0x02, 0x0d, 0xbb, 0x75, 0x29, 0x01, 0x75, 0x2a, 0x61, 0xe4, 0xf5, 0x28, 0x22, 0x78, 0xff,
0xe4, 0xf6, 0xd8, 0xfd, 0x90, 0x00, 0x00, 0x7f, 0x00, 0x7e, 0x03, 0xe4, 0xf0, 0xa3, 0xdf, 0xfc,
0xde, 0xfa, 0x75, 0x81, 0x74, 0x75, 0xa0, 0x00, 0x02, 0x2c, 0x06, 0x02, 0x33, 0xd3, 0xe4, 0x93,
0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29,
0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20,
0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02,
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x39, 0xbf, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3,
0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf,
0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8,
0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82,
0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0x90, 0x36, 0x0a, 0xe4, 0x93,
0x70, 0x05, 0x43, 0x90, 0x10, 0x80, 0x03, 0x53, 0x90, 0xef, 0x90, 0x36, 0x0c, 0xe4, 0x93, 0xff,
0x7c, 0x01, 0x7d, 0x00, 0x12, 0x33, 0x94, 0x90, 0x36, 0x0d, 0xe4, 0x93, 0xb4, 0x01, 0x07, 0x90,
0xff, 0x10, 0xe0, 0x44, 0x18, 0xf0, 0x7e, 0x01, 0x7f, 0x00, 0x7d, 0x00, 0x7b, 0x01, 0x7a, 0x01,
0x79, 0x00, 0x12, 0x10, 0x98, 0x7d, 0x01, 0x7f, 0x12, 0x12, 0x32, 0xcc, 0x7d, 0x03, 0x7f, 0x12,
0x12, 0x30, 0xb1, 0x90, 0xff, 0x1b, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xff, 0x14, 0xe0, 0x44, 0x04,
0xf0, 0x90, 0x36, 0x09, 0xe4, 0x93, 0x90, 0x01, 0xfa, 0xf0, 0x90, 0x36, 0x07, 0xe4, 0x93, 0x90,
0x01, 0xea, 0xf0, 0x90, 0x36, 0x11, 0xe4, 0x93, 0x90, 0x01, 0xed, 0xf0, 0x78, 0xa7, 0x7c, 0x01,
0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x36, 0x79, 0x00, 0x7e, 0x00, 0x7f, 0x03, 0x12, 0x0c, 0x68, 0xe4,
0x90, 0x01, 0xec, 0xf0, 0x90, 0x01, 0xfe, 0x04, 0xf0, 0xe4, 0x78, 0x73, 0xf6, 0x90, 0x00, 0xca,
0xf0, 0xa3, 0xf0, 0x22, 0x8f, 0x1c, 0x8c, 0x1d, 0x8d, 0x1e, 0xe4, 0xff, 0x79, 0x01, 0xe4, 0xf5,
0x1f, 0xfe, 0x12, 0x35, 0xf3, 0xe5, 0x82, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe4,
0x93, 0x25, 0xe0, 0x25, 0x1c, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0x12, 0x35, 0xf3, 0x74, 0x04,
0x93, 0xfa, 0x74, 0x05, 0x93, 0xfb, 0xc3, 0xed, 0x9b, 0xec, 0x9a, 0x40, 0x02, 0x05, 0x1f, 0x0e,
0xbe, 0x04, 0xcf, 0x12, 0x35, 0xf3, 0x74, 0x06, 0x93, 0xfd, 0xe5, 0x1f, 0xc3, 0x9d, 0x50, 0x04,
0xe4, 0xf9, 0x80, 0x04, 0x0f, 0xbf, 0x05, 0xb6, 0x90, 0x00, 0xcd, 0xe0, 0xb5, 0x01, 0x07, 0xe4,
0x90, 0x00, 0xcc, 0xf0, 0x80, 0x28, 0x90, 0x00, 0xcc, 0xe0, 0x04, 0xf0, 0x85, 0x1e, 0x82, 0x85,
0x1d, 0x83, 0x74, 0x23, 0x93, 0xff, 0x90, 0x00, 0xcc, 0xe0, 0xfd, 0x33, 0x95, 0xe0, 0xfc, 0xd3,
0xed, 0x9f, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x40, 0x05, 0xe4, 0xf0, 0xa3, 0xe9, 0xf0, 0x90, 0x00,
0xcd, 0xe0, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0xaa, 0x22, 0xe4, 0x78, 0x4f, 0xf6, 0x08, 0xf6, 0xfe,
0xfd, 0x12, 0x01, 0xb8, 0x12, 0x02, 0xe5, 0xe4, 0xf9, 0xf5, 0x30, 0xf5, 0x2e, 0x75, 0x2f, 0xff,
0x78, 0x67, 0xe6, 0xff, 0xe9, 0xc3, 0x9f, 0x50, 0x5b, 0xe9, 0x12, 0x00, 0xed, 0xe9, 0x25, 0xe0,
0x25, 0xe0, 0x24, 0x60, 0xf8, 0xe2, 0x2f, 0xf5, 0x32, 0x18, 0xe2, 0x3e, 0xf5, 0x31, 0x12, 0x03,
0x55, 0x78, 0x4f, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xef, 0x2d, 0xfb, 0xee, 0x3c, 0xfa, 0xd3, 0xe5,
0x32, 0x9b, 0xe5, 0x31, 0x9a, 0x40, 0x06, 0x75, 0x30, 0x01, 0x18, 0x80, 0x1d, 0xe5, 0x32, 0x2f,
0xff, 0xe5, 0x31, 0x3e, 0xfe, 0xd3, 0xed, 0x9f, 0xec, 0x9e, 0x40, 0x15, 0xe5, 0x30, 0x60, 0x08,
0xe4, 0xf5, 0x30, 0x12, 0x31, 0xf6, 0x05, 0x2e, 0x78, 0x4f, 0xa6, 0x31, 0x08, 0xa6, 0x32, 0x89,
0x2f, 0x09, 0x80, 0x9c, 0xe5, 0x30, 0x60, 0x03, 0x12, 0x31, 0xf6, 0x22, 0xe4, 0xfb, 0x12, 0x03,
0x71, 0xfa, 0xf4, 0x60, 0x62, 0xea, 0x70, 0x0c, 0x12, 0x00, 0x60, 0x74, 0x11, 0x93, 0xf5, 0x2e,
0x74, 0x12, 0x80, 0x1d, 0x78, 0x67, 0xe6, 0x14, 0xb5, 0x02, 0x0c, 0x12, 0x00, 0x60, 0x74, 0x13,
0x93, 0xf5, 0x2e, 0x74, 0x14, 0x80, 0x0a, 0x12, 0x00, 0x60, 0x74, 0x0f, 0x93, 0xf5, 0x2e, 0x74,
0x10, 0x93, 0xf5, 0x2f, 0x78, 0x0d, 0xe2, 0x70, 0x05, 0x78, 0x3c, 0xe2, 0x60, 0x0e, 0xe5, 0x2f,
0x25, 0xe0, 0xff, 0xe5, 0x2e, 0x12, 0x05, 0xde, 0x8e, 0x2e, 0x8f, 0x2f, 0xea, 0x12, 0x00, 0xed,
0xea, 0x25, 0xe0, 0x12, 0x02, 0xd8, 0xc3, 0xef, 0x95, 0x2f, 0xee, 0x95, 0x2e, 0x50, 0x08, 0xeb,
0x25, 0xe0, 0x24, 0x68, 0xf8, 0x76, 0xff, 0x0b, 0xeb, 0x64, 0x02, 0x70, 0x91, 0x78, 0x68, 0xe6,
0xb4, 0xff, 0x0a, 0x78, 0x6a, 0xe6, 0xff, 0xf4, 0x60, 0x03, 0x12, 0x01, 0x97, 0x22, 0xef, 0x54,
0x07, 0xfe, 0x74, 0x01, 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf9, 0xf4, 0xfe,
0xef, 0x54, 0xf0, 0xf5, 0x3e, 0x64, 0x10, 0x70, 0x1e, 0xbd, 0x08, 0x02, 0x7d, 0x02, 0x90, 0xff,
0x12, 0xed, 0x30, 0xe2, 0x05, 0xe0, 0x49, 0xf0, 0x80, 0x03, 0xe0, 0x5e, 0xf0, 0xe5, 0x82, 0x15,
0x82, 0x70, 0x14, 0x15, 0x83, 0x80, 0x10, 0xe5, 0x3e, 0x13, 0x13, 0x54, 0x3f, 0x24, 0x11, 0xfb,
0xe4, 0x34, 0xff, 0xf5, 0x83, 0x8b, 0x82, 0xed, 0x24, 0xfb, 0x60, 0x14, 0x14, 0x60, 0x20, 0x24,
0xfe, 0x70, 0x2a, 0xe0, 0x5e, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x1e, 0x15, 0x83, 0x80, 0x1a,
0xe0, 0x5e, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x49, 0xf0, 0x22, 0xe0,
0x49, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x5e, 0xf0, 0x22, 0xc0, 0xe0,
0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x78, 0x40, 0xa6, 0xa3, 0x08, 0xa6, 0xa6,
0x75, 0xa3, 0x08, 0xe6, 0xff, 0x30, 0xe4, 0x07, 0x75, 0xd1, 0xdf, 0x78, 0x72, 0x76, 0x00, 0x78,
0x40, 0xe6, 0x30, 0xe0, 0x40, 0xef, 0x20, 0xe0, 0x39, 0x78, 0x72, 0xe6, 0xff, 0x70, 0x18, 0x90,
0x02, 0xf8, 0xe0, 0xfe, 0xf5, 0xd6, 0x18, 0xee, 0xf6, 0xc3, 0x94, 0x10, 0x50, 0x24, 0x78, 0x73,
0xe6, 0x25, 0xd6, 0xf5, 0xd6, 0x80, 0x1b, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5,
0x83, 0xe0, 0xff, 0x78, 0x71, 0xe6, 0x06, 0x25, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x08, 0xf5, 0x83,
0xef, 0xf0, 0x78, 0x72, 0x06, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0xab, 0x07,
0xaa, 0x05, 0xe4, 0x78, 0x62, 0xf6, 0xeb, 0x12, 0x14, 0xee, 0xe0, 0xf5, 0x29, 0xa3, 0xe0, 0xf5,
0x2a, 0x78, 0x5d, 0xe6, 0x75, 0x27, 0x00, 0xf5, 0x28, 0xae, 0x27, 0xff, 0x7c, 0x00, 0x7d, 0xfc,
0x12, 0x0d, 0x08, 0xd3, 0xe5, 0x2a, 0x9f, 0xe5, 0x29, 0x9e, 0x40, 0x06, 0x78, 0x62, 0xe6, 0x44,
0x20, 0xf6, 0x12, 0x14, 0xd2, 0x74, 0x05, 0x93, 0x25, 0xe0, 0xf5, 0x2a, 0x74, 0x04, 0x93, 0x33,
0xf5, 0x29, 0xeb, 0x12, 0x15, 0x27, 0xe0, 0xfe, 0xa3, 0xe0, 0x25, 0x2a, 0xff, 0xe5, 0x29, 0x3e,
0xfe, 0xeb, 0x12, 0x14, 0xee, 0xe0, 0xfc, 0xa3, 0xe0, 0xd3, 0x9f, 0xec, 0x9e, 0x40, 0x09, 0x78,
0x62, 0xe6, 0x44, 0x02, 0xf6, 0x44, 0x08, 0xf6, 0x0b, 0x1a, 0xea, 0x70, 0x99, 0x22, 0xe4, 0xf5,
0x1c, 0x78, 0x1d, 0x7c, 0x00, 0xfd, 0x7b, 0xff, 0x7a, 0x39, 0x79, 0xf6, 0xfe, 0x7f, 0x02, 0x12,
0x0c, 0x68, 0x75, 0x22, 0x01, 0x75, 0x23, 0x00, 0x75, 0x24, 0xc4, 0x7b, 0x00, 0x7a, 0x00, 0x79,
0x1d, 0x12, 0x25, 0x87, 0xe5, 0x1d, 0xf4, 0x60, 0x14, 0x90, 0x00, 0xc4, 0x12, 0x31, 0xce, 0x40,
0x09, 0xd3, 0xef, 0x94, 0xb8, 0xee, 0x94, 0x0b, 0x40, 0x03, 0x75, 0x1c, 0x01, 0xe5, 0x1e, 0xf4,
0x60, 0x14, 0x90, 0x00, 0xc6, 0x12, 0x31, 0xce, 0x40, 0x09, 0xd3, 0xef, 0x94, 0xb8, 0xee, 0x94,
0x0b, 0x40, 0x03, 0x75, 0x1c, 0x01, 0x78, 0xb0, 0x7c, 0x01, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x00,
0x79, 0xc4, 0x7e, 0x00, 0x7f, 0x04, 0x12, 0x0c, 0x68, 0xaf, 0x1c, 0x22, 0x12, 0x04, 0xd6, 0x60,
0x11, 0xa8, 0x07, 0xe8, 0x24, 0x0b, 0xf8, 0xe2, 0x7f, 0x80, 0x60, 0x02, 0x7f, 0x08, 0x8f, 0x22,
0x80, 0x1e, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x0b, 0xf8, 0xe2, 0x60, 0x11, 0xa8, 0x07, 0xe8, 0x24,
0x0f, 0xf8, 0xe2, 0x7f, 0x04, 0x60, 0x02, 0x7f, 0x08, 0x8f, 0x22, 0x80, 0x03, 0xe4, 0xf5, 0x22,
0xe5, 0x22, 0xb4, 0x04, 0x0f, 0x12, 0x03, 0x64, 0x04, 0x12, 0x00, 0xe0, 0x78, 0x66, 0xe6, 0x24,
0x05, 0xf8, 0xe4, 0xf2, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x06, 0xf8, 0xe5, 0x22, 0xf2, 0xef, 0x04,
0x12, 0x03, 0x6a, 0x24, 0x07, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x06, 0x02, 0x0c,
0x68, 0xef, 0x54, 0x07, 0x90, 0x39, 0xee, 0x93, 0xfe, 0xf4, 0xf9, 0xef, 0x54, 0xf0, 0xff, 0x64,
0x10, 0x60, 0x11, 0xef, 0x13, 0x13, 0x54, 0x3f, 0x24, 0x11, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xfa,
0xab, 0x82, 0x80, 0x1a, 0xbd, 0x08, 0x02, 0x7d, 0x02, 0x7a, 0xff, 0x7b, 0x12, 0xed, 0x30, 0xe2,
0x05, 0x12, 0x35, 0xcd, 0x80, 0x03, 0x12, 0x35, 0xd5, 0xeb, 0x1b, 0x70, 0x01, 0x1a, 0xed, 0x30,
0xe1, 0x05, 0x12, 0x35, 0xcd, 0x80, 0x03, 0x12, 0x35, 0xd5, 0xeb, 0x1b, 0x70, 0x01, 0x1a, 0xed,
0x30, 0xe0, 0x04, 0x12, 0x35, 0xcd, 0x22, 0x12, 0x35, 0xd5, 0x22, 0x78, 0x63, 0xe6, 0xff, 0x78,
0x63, 0xe6, 0x60, 0x29, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x14, 0x84, 0x50, 0x03, 0xe0, 0x04,
0xf0, 0x12, 0x16, 0x4e, 0x30, 0xe7, 0x08, 0x12, 0x14, 0x84, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x78,
0x63, 0xe6, 0x6f, 0x60, 0xda, 0xe6, 0xff, 0x12, 0x15, 0xe4, 0xf0, 0x80, 0xd2, 0xe4, 0xff, 0x78,
0x65, 0xe6, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x14, 0x12, 0x15, 0x7c, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd,
0xef, 0x12, 0x14, 0xee, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x0f, 0x80, 0xe3, 0x22, 0x8f, 0x2d, 0xe4,
0xfd, 0x7f, 0x12, 0x12, 0x32, 0xcc, 0xaf, 0x2d, 0x15, 0x2d, 0xef, 0x60, 0x38, 0x75, 0xb1, 0x11,
0x75, 0xb4, 0x63, 0x75, 0xb0, 0x0d, 0xe5, 0xb1, 0x20, 0xe0, 0x22, 0xe5, 0x89, 0x30, 0xe7, 0x08,
0x12, 0x2b, 0x86, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x75, 0x91, 0xc1, 0xe4, 0xf5, 0x91, 0xe5, 0x89,
0x30, 0xe7, 0xe3, 0x12, 0x2b, 0x86, 0x50, 0xde, 0xe0, 0x04, 0xf0, 0x80, 0xd9, 0xe4, 0xf5, 0xb0,
0x75, 0xb1, 0x01, 0x80, 0xc1, 0x7d, 0x01, 0x7f, 0x12, 0x02, 0x32, 0xcc, 0x85, 0x0b, 0x82, 0x85,
0x0a, 0x83, 0x22, 0x75, 0x89, 0x80, 0x90, 0x00, 0xc3, 0xe0, 0xc3, 0x94, 0xff, 0x22, 0x75, 0x8a,
0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x43, 0x22, 0xe0, 0xfe,
0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x78, 0xee, 0x94, 0x00, 0x22, 0xe4, 0x93, 0xff, 0x7e, 0x00, 0x7c,
0x00, 0x02, 0x0d, 0x08, 0xe4, 0x78, 0x88, 0xf2, 0x08, 0xf2, 0x90, 0x00, 0xc8, 0xf0, 0x22, 0xab,
0x25, 0xaa, 0x26, 0xa9, 0x27, 0x22, 0x78, 0x4f, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0xad, 0x2f, 0xaf,
0x2e, 0xef, 0xc3, 0x94, 0x02, 0x50, 0x0e, 0xef, 0x25, 0xe0, 0x24, 0x68, 0xf8, 0xa6, 0x05, 0xef,
0x12, 0x01, 0xe3, 0x80, 0x24, 0xc3, 0x90, 0x00, 0xb6, 0xe0, 0x9b, 0x90, 0x00, 0xb5, 0xe0, 0x9a,
0x50, 0x06, 0x78, 0x68, 0xa6, 0x05, 0x80, 0x11, 0xc3, 0x90, 0x00, 0xb8, 0xe0, 0x9b, 0x90, 0x00,
0xb7, 0xe0, 0x9a, 0x50, 0x09, 0x78, 0x6a, 0xa6, 0x05, 0xea, 0xf0, 0xa3, 0xeb, 0xf0, 0x22, 0xc0,
0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01,
0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x16, 0x96, 0x12,
0x00, 0x0a, 0x7b, 0xff, 0x7a, 0x2e, 0x79, 0x7e, 0x12, 0x27, 0xf2, 0xd0, 0x07, 0xd0, 0x06, 0xd0,
0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0,
0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x8f, 0x2a, 0x8d, 0x2b, 0xe5, 0x2b, 0x75, 0xf0, 0x2f, 0xa4,
0x24, 0x0a, 0x12, 0x00, 0xf3, 0xe5, 0x2a, 0x12, 0x05, 0x17, 0x12, 0x32, 0xbd, 0xc0, 0x06, 0xc0,
0x07, 0xe5, 0x2b, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x08, 0x12, 0x00, 0xf3, 0xe5, 0x2a, 0x12, 0x05,
0xb8, 0x12, 0x32, 0xbd, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0x22, 0xf8, 0xe2, 0xfc,
0x08, 0xe2, 0xc3, 0x9f, 0xff, 0xec, 0x9e, 0xfe, 0x12, 0x39, 0xa3, 0x22, 0x12, 0x35, 0xbd, 0x60,
0x3e, 0xee, 0x64, 0x01, 0x70, 0x18, 0xed, 0x60, 0x07, 0x78, 0x74, 0xe6, 0x4c, 0xf6, 0x80, 0x06,
0xec, 0xf4, 0x78, 0x74, 0x56, 0xf6, 0x78, 0x74, 0xe6, 0x90, 0xff, 0x18, 0xf0, 0x22, 0xaf, 0x06,
0xef, 0x75, 0xf0, 0x04, 0xa4, 0x24, 0x12, 0xff, 0xe5, 0xf0, 0x34, 0xff, 0x8f, 0x82, 0xf5, 0x83,
0xed, 0x60, 0x04, 0xe0, 0x4c, 0xf0, 0x22, 0xe0, 0xff, 0xec, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x22,
0xc2, 0xd5, 0xe8, 0x30, 0xe7, 0x0f, 0xb2, 0xd5, 0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, 0xe4,
0x99, 0xf9, 0xe4, 0x98, 0xf8, 0xec, 0x30, 0xe7, 0x17, 0xb2, 0xd5, 0x12, 0x33, 0x46, 0x12, 0x0f,
0x42, 0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, 0xe4, 0x99, 0xf9, 0xe4, 0x98, 0xf8, 0x80, 0x03,
0x12, 0x0f, 0x42, 0x30, 0xd5, 0x0d, 0xe4, 0xc3, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0xe4, 0x9d, 0xfd,
0xe4, 0x9c, 0xfc, 0x22, 0x12, 0x0c, 0xe6, 0xab, 0x1c, 0xe5, 0x1e, 0x24, 0x0c, 0xf9, 0xe4, 0x35,
0x1d, 0xfa, 0x7e, 0x00, 0xe9, 0x25, 0x25, 0xf9, 0xee, 0x3a, 0xfa, 0x12, 0x0c, 0x8e, 0xff, 0x22,
0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x90, 0x00, 0x0b, 0x12, 0x0c, 0xa7, 0xff, 0x22, 0x75, 0x8a,
0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x22, 0xab, 0x22, 0xaa, 0x23, 0xa9, 0x24, 0x85, 0x25, 0x82,
0x75, 0x83, 0x00, 0x22, 0x8c, 0x08, 0x8d, 0x09, 0x12, 0x39, 0x5a, 0x44, 0x18, 0x12, 0x39, 0x51,
0x90, 0xff, 0x14, 0xe0, 0x44, 0x18, 0xf0, 0x90, 0xff, 0x1b, 0xe0, 0x44, 0x18, 0xf0, 0x75, 0xa3,
0x08, 0xef, 0x44, 0x80, 0xf5, 0xa1, 0x75, 0xa6, 0x28, 0x75, 0xa2, 0xc1, 0xaf, 0x09, 0x85, 0x08,
0xd7, 0x8f, 0xd6, 0x75, 0xd5, 0x02, 0x75, 0xd4, 0xf8, 0x75, 0xd2, 0x01, 0x75, 0xd1, 0xdf, 0x53,
0xac, 0xef, 0x22, 0xc2, 0xaf, 0x12, 0x35, 0x07, 0xe5, 0x9b, 0xb4, 0x5a, 0x16, 0xe5, 0x9a, 0xb4,
0xa5, 0x11, 0xe5, 0x99, 0xb4, 0xf0, 0x0c, 0xe5, 0x98, 0xb4, 0x0f, 0x07, 0x90, 0xff, 0x85, 0xe0,
0x44, 0x20, 0xf0, 0x75, 0x8a, 0x0a, 0xd2, 0xaf, 0x7f, 0x0a, 0x12, 0x34, 0x46, 0x12, 0x39, 0x7a,
0x12, 0x10, 0xc4, 0x75, 0x8a, 0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x80, 0xf3, 0xad, 0x07, 0x7f,
0x3a, 0x12, 0x35, 0xdd, 0x90, 0x00, 0xc1, 0xe4, 0xf0, 0xa3, 0xef, 0xf0, 0x7f, 0x3b, 0x12, 0x35,
0xdd, 0xef, 0xfb, 0x7a, 0x00, 0x90, 0x00, 0xc2, 0xe0, 0xfe, 0xe4, 0x2b, 0xff, 0xea, 0x3e, 0x90,
0x00, 0xc1, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0xc1, 0xe0, 0xb4, 0x80, 0x08, 0xa3, 0xe0, 0xb4,
0x67, 0x03, 0xbd, 0xb6, 0xf1, 0x22, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x90, 0x00, 0xc3, 0xf0, 0xef,
0x70, 0x0e, 0x75, 0x88, 0x08, 0xf5, 0x8d, 0xf5, 0x8c, 0xf5, 0x8f, 0xf5, 0x8e, 0xf5, 0x88, 0x22,
0x75, 0x88, 0x08, 0xe4, 0xf5, 0x8d, 0xf5, 0x8c, 0xef, 0x75, 0xf0, 0x20, 0xa4, 0xff, 0xe5, 0xf0,
0x44, 0x80, 0xf5, 0x8f, 0x8f, 0x8e, 0x75, 0x88, 0xa0, 0x22, 0xe4, 0xf5, 0x3c, 0xf5, 0x3d, 0xff,
0x12, 0x0c, 0x8e, 0x25, 0x3d, 0xf5, 0x3d, 0xe4, 0x35, 0x3c, 0xf5, 0x3c, 0x90, 0xff, 0xff, 0x12,
0x0c, 0xa7, 0x12, 0x0c, 0xd4, 0x74, 0xff, 0x29, 0xf9, 0x74, 0xff, 0x3a, 0xfa, 0x0f, 0xbf, 0x09,
0xdf, 0xed, 0x12, 0x0c, 0xd4, 0xae, 0x3c, 0xaf, 0x3d, 0x22, 0x12, 0x35, 0xbd, 0x60, 0x29, 0x90,
0xff, 0x13, 0xee, 0xd3, 0x94, 0x03, 0x40, 0x11, 0xaf, 0x06, 0xef, 0x75, 0xf0, 0x04, 0xa4, 0x25,
0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0xed, 0x60, 0x04, 0xe0, 0x4c, 0xf0, 0x22,
0xe0, 0xff, 0xec, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x22, 0x85, 0x21, 0x82, 0x85, 0x20, 0x83, 0x22,
0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x12, 0x0d, 0xbb, 0xff, 0x22, 0xab, 0x1c, 0xaa, 0x1d, 0xa9,
0x1e, 0x90, 0x00, 0x02, 0x12, 0x0d, 0xe6, 0xff, 0x22, 0x93, 0xfd, 0xd3, 0x90, 0x00, 0xbe, 0xe0,
0x9d, 0x90, 0x00, 0xbd, 0xe0, 0x9c, 0x22, 0x75, 0x9b, 0x5a, 0x75, 0x9a, 0xa5, 0x75, 0x99, 0xf0,
0x75, 0x98, 0x0f, 0x75, 0xac, 0xff, 0x75, 0xad, 0xff, 0x90, 0xff, 0x88, 0x74, 0x40, 0xf0, 0x74,
0xc0, 0xf0, 0x90, 0xff, 0x01, 0x74, 0x01, 0xf0, 0x75, 0x95, 0xf1, 0xe4, 0xf5, 0x96, 0x75, 0x97,
0xc7, 0x22, 0xef, 0x60, 0x0f, 0x43, 0xac, 0x10, 0x12, 0x39, 0x5a, 0x54, 0xe7, 0x12, 0x39, 0x51,
0xe4, 0xf5, 0xa2, 0x22, 0x12, 0x39, 0x52, 0xa3, 0xe0, 0x44, 0x18, 0xf0, 0xa3, 0xe0, 0x54, 0xe7,
0xf0, 0x75, 0xa2, 0xc1, 0x53, 0xac, 0xef, 0x22, 0xc3, 0xef, 0x94, 0x01, 0xee, 0x64, 0x80, 0x94,
0x80, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x11, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x0a,
0xed, 0x24, 0xff, 0xff, 0xec, 0x34, 0xff, 0xfe, 0x80, 0x00, 0x22, 0xe4, 0x78, 0x6d, 0xf6, 0x8f,
0x82, 0x8e, 0x83, 0x74, 0x55, 0x93, 0x78, 0x67, 0xf6, 0xef, 0x24, 0x55, 0xf5, 0x0f, 0xe4, 0x3e,
0xf5, 0x0e, 0x78, 0x00, 0xe2, 0x54, 0xfe, 0xf2, 0x54, 0xfb, 0xf2, 0x22, 0xab, 0x1f, 0xaa, 0x20,
0xa9, 0x21, 0x90, 0x00, 0x01, 0x12, 0x0c, 0xa7, 0xff, 0x22, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff,
0x58, 0xf0, 0xab, 0x1f, 0xaa, 0x20, 0xa9, 0x21, 0x12, 0x0c, 0x8e, 0xff, 0x22, 0xef, 0x54, 0x07,
0x90, 0x39, 0xee, 0x93, 0xfc, 0xef, 0xc4, 0x54, 0x0f, 0xfe, 0xef, 0xf4, 0x22, 0x8b, 0x82, 0x8a,
0x83, 0xe0, 0x4e, 0xf0, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe0, 0x59, 0xf0, 0x22, 0x90, 0xff, 0x00,
0x74, 0x02, 0xf0, 0x90, 0xff, 0x04, 0xe4, 0xf0, 0x90, 0xff, 0x03, 0xef, 0xf0, 0x90, 0xff, 0x07,
0xe0, 0xff, 0x22, 0x85, 0x1e, 0x82, 0x85, 0x1d, 0x83, 0x75, 0xf0, 0x07, 0xef, 0x02, 0x10, 0x59,
0xb6, 0x11, 0x01, 0x0a, 0x14, 0x01, 0x02, 0x05, 0x3c, 0x70, 0x00, 0x00, 0x15, 0x00, 0x02, 0x01,
0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x03, 0x0a, 0x00, 0xc8, 0x03, 0xe8, 0x0f, 0x1e, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50,
0x44, 0x41, 0x45, 0x51, 0x46, 0x52, 0x56, 0x53, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28,
0x05, 0x0b, 0x28, 0xff, 0xff, 0xff, 0x64, 0x1e, 0x90, 0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8,
0x00, 0x14, 0x02, 0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85,
0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05,
0x00, 0xef, 0x00, 0xef, 0x00, 0x46, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c,
0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c,
0x00, 0x0a, 0x14, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c,
0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, 0x44, 0x41, 0x45,
0x51, 0x46, 0x52, 0x56, 0x53, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, 0x05, 0x0b, 0x28,
0xff, 0xff, 0xff, 0x64, 0x1e, 0x90, 0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02,
0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00,
0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, 0x00, 0xf0, 0x00,
0xf0, 0x00, 0x46, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01,
0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, 0x00, 0x0a, 0x14,
0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, 0x04, 0x02, 0x03,
0x07, 0x06, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, 0x44, 0x41, 0x45, 0x51, 0x46, 0x52,
0x56, 0x53, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, 0x05, 0x0b, 0x28, 0xff, 0xff, 0xff,
0x64, 0x1e, 0x90, 0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, 0x58, 0x09, 0x09,
0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58,
0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x46,
0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01,
0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, 0x00, 0x0a, 0x14, 0x02, 0x03, 0x07,
0x06, 0x01, 0x2c, 0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01,
0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, 0x44, 0x41, 0x45, 0x51, 0x46, 0x52, 0x56, 0x53, 0x55,
0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, 0x05, 0x0b, 0x28, 0xff, 0xff, 0xff, 0x64, 0x1e, 0x90,
0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, 0x58, 0x09, 0x09, 0x85, 0x00, 0xc8,
0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85,
0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x46, 0x00, 0x46, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04,
0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, 0x00, 0x0a, 0x14, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c,
0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x02,
0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0e, 0x10,
0x3c, 0x01, 0x00, 0x64, 0x10, 0x41, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x46, 0x45, 0x44, 0x43,
0x17, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa0, 0x22, 0x90, 0x00, 0x00, 0x08,
0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, 0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, 0x00, 0x28, 0x02,
0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00,
0x3c, 0x02, 0x58, 0x07, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00,
0x00, 0x02, 0x08, 0xfa, 0x00, 0x64, 0x14, 0x02, 0x03, 0x0b, 0x0a, 0x00, 0xc8, 0x04, 0x00, 0x01,
0x0c, 0x0d, 0x00, 0x96, 0x04, 0x02, 0x03, 0x0b, 0x0a, 0x00, 0xc8, 0x04, 0x02, 0x03, 0x0b, 0x0a,
0x00, 0xc8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xe4, 0x90, 0x00, 0xcd, 0xf0,
0x8f, 0x82, 0x8e, 0x83, 0x74, 0x23, 0x93, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x00, 0xcc, 0xf0,
0x22, 0xf0, 0x90, 0xff, 0x10, 0xe0, 0x54, 0xe7, 0xf0, 0x22, 0x90, 0xff, 0x12, 0xe0, 0x54, 0xe7,
0xf0, 0x90, 0xff, 0x11, 0xe0, 0x22, 0xef, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x03, 0xf5, 0x82, 0xe4,
0x34, 0x02, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x22, 0x12, 0x2c, 0x4b, 0x78, 0x6f, 0x76,
0x00, 0x08, 0x76, 0x28, 0x90, 0x00, 0xc9, 0x74, 0x04, 0xf0, 0x22, 0x8d, 0x22, 0xaf, 0x22, 0x12,
0x24, 0x44, 0xaf, 0x22, 0x02, 0x16, 0xc9, 0xef, 0x25, 0xe0, 0x24, 0x5f, 0xf8, 0xe2, 0xfe, 0x08,
0xe2, 0xff, 0x22, 0xee, 0x30, 0xe7, 0x07, 0xc3, 0xe4, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x22, 0x12,
0x31, 0xac, 0x74, 0x78, 0x93, 0xfd, 0x02, 0x05, 0xfc, 0x7f, 0x30, 0x12, 0x35, 0xdd, 0x22, 0x41,
0x00, 0xc8, 0x00, 0x00, 0x78, 0x61, 0xa6, 0x07, 0x22, 0x12, 0x39, 0x66, 0x22, 0x7f, 0x00, 0x22,
0x11, 0x10, 0x41, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x46, 0x45, 0x44, 0x43, 0x17, 0x16, 0x11,
0x40, 0x41, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x46, 0x45, 0x44, 0x43, 0x42, 0x16, 0x01, 0x02,
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb6, 0x02, 0x30, 0x21, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x56,
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,558 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst226se.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst226se_fw.h"
#define BOOT_I2C_ADDR (0x5A)
#define MAIN_I2C_ADDR (0x5A)
#define RW_REG_LEN (2)
#define CST226SE_BIN_SIZE (7*1024+512)
static struct hyn_ts_data *hyn_226data = NULL;
static const u8 gest_map_tbl[33] = {0xff,4,1,3,2,5,12,6,7,7,9,11,10,13,12,7,7,6,10,6,5,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,14};
static int cst226se_updata_judge(u8 *p_fw, u16 len);
static u32 cst226se_read_checksum(void);
static int cst226se_updata_tpinfo(void);
static int cst226se_enter_boot(void);
static int cst226se_set_workmode(enum work_mode mode,u8 enable);
static void cst226se_rst(void);
static int cst226se_init(struct hyn_ts_data* ts_data)
{
int ret = 0;
u8 buf[4];
HYN_ENTER();
hyn_226data = ts_data;
ret = cst226se_enter_boot();
if(ret){
HYN_ERROR("cst226se_enter_boot failed");
return -1;
}
hyn_226data->fw_updata_addr = (u8*)fw_bin;
hyn_226data->fw_updata_len = CST226SE_BIN_SIZE;
hyn_226data->hw_info.ic_fw_checksum = cst226se_read_checksum();
hyn_wr_reg(hyn_226data,0xA006EE,3,buf,0); //exit boot
cst226se_rst();
mdelay(50);
hyn_set_i2c_addr(hyn_226data,MAIN_I2C_ADDR);
hyn_226data->need_updata_fw = cst226se_updata_judge((u8*)fw_bin,CST226SE_BIN_SIZE);
if(hyn_226data->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
return 0;
}
static int cst226se_report(void)
{
u8 buf[80]={0};
u8 finger_num = 0,key_flg = 0,tmp_dat;
int len = 0;
int ret = 0,retry = 2;
switch(hyn_226data->work_mode){
case NOMAL_MODE:
retry = 2;
while(retry--){
ret = hyn_wr_reg(hyn_226data,0xD000,2,buf,7);
finger_num = buf[5] & 0x7F;
if(ret || buf[6] != 0xAB || buf[0] == 0xAB || finger_num > MAX_POINTS_REPORT){
ret = -2;
continue;
}
key_flg = (buf[5]&0x80) ? 1:0;
len = 0;
if(finger_num > 1){
len += (finger_num-1)*5;
}
if(key_flg && finger_num){
len += 3;
}
if(len > 0){
ret = hyn_wr_reg(hyn_226data,0xD007,2,&buf[5],len);
}
ret |= hyn_wr_reg(hyn_226data,0xD000AB,3,buf,0);
if(ret){
ret = -3;
continue;
}
ret = 0;
break;
}
if(ret){
hyn_wr_reg(hyn_226data,0xD000AB,3,buf,0);
HYN_ERROR("read frame failed");
break;
}
if(key_flg){ //key
if(hyn_226data->rp_buf.report_need == REPORT_NONE){
hyn_226data->rp_buf.report_need |= REPORT_KEY;
}
len = finger_num ? (len+5):3;
hyn_226data->rp_buf.key_id = (buf[len-2]>>4)-1;
hyn_226data->rp_buf.key_state = (buf[len-3]&0x0F)==0x03 ? 1:0;
HYN_INFO("key_id:%x state:%x",hyn_226data->rp_buf.key_id ,hyn_226data->rp_buf.key_state);
}
if(finger_num){
u16 index = 0,i = 0;
u8 touch_down = 0;
if(hyn_226data->rp_buf.report_need == REPORT_NONE){
hyn_226data->rp_buf.report_need |= REPORT_POS;
}
hyn_226data->rp_buf.rep_num = finger_num;
for(i = 0; i < finger_num; i++){
index = i*5;
hyn_226data->rp_buf.pos_info[i].pos_id = (buf[index]>>4)&0x0F;
hyn_226data->rp_buf.pos_info[i].event = (buf[index]&0x0F) == 0x06 ? 1 : 0;
hyn_226data->rp_buf.pos_info[i].pos_x = ((u16)buf[index + 1]<<4) + ((buf[index + 3] >> 4) & 0x0F);
hyn_226data->rp_buf.pos_info[i].pos_y = ((u16)buf[index + 2]<<4) + (buf[index + 3] & 0x0F);
hyn_226data->rp_buf.pos_info[i].pres_z = buf[index + 4];
if(hyn_226data->rp_buf.pos_info[i].event) touch_down++;
// HYN_INFO("report_id = %d, xy = %d,%d",hyn_226data->rp_buf.pos_info[i].pos_id,hyn_226data->rp_buf.pos_info[i].pos_x,hyn_226data->rp_buf.pos_info[i].pos_y);
}
if(0== touch_down){
hyn_226data->rp_buf.rep_num = 0;
}
}
break;
case GESTURE_MODE:
ret = hyn_wr_reg(hyn_226data,0xD04C,2,&tmp_dat,1);
if((tmp_dat&0x7F) <= 32){
tmp_dat = tmp_dat&0x7F;
hyn_226data->gesture_id = gest_map_tbl[tmp_dat];
hyn_226data->rp_buf.report_need |= REPORT_GES;
}
break;
default:
break;
}
return ret;
}
static int cst226se_prox_handle(u8 cmd)
{
int ret = 0;
HYN_ENTER();
switch(cmd){
case 1: //enable
hyn_226data->prox_is_enable = 1;
hyn_226data->prox_state = 0;
ret = hyn_wr_reg(hyn_226data,0xD004B01,3,NULL,0);
break;
case 0: //disable
hyn_226data->prox_is_enable = 0;
hyn_226data->prox_state = 0;
ret = hyn_wr_reg(hyn_226data,0xD004B00,3,NULL,0);
break;
case 2: //read
ret = hyn_wr_reg(hyn_226data,0xD004B,2,&hyn_226data->prox_state,1);
break;
}
return ret;
}
static int cst226se_set_workmode(enum work_mode mode,u8 enable)
{
int ret = 0;
HYN_ENTER();
hyn_226data->work_mode = mode;
if(mode != NOMAL_MODE)
hyn_esdcheck_switch(hyn_226data,DISABLE);
switch(mode){
case NOMAL_MODE:
hyn_irq_set(hyn_226data,ENABLE);
hyn_esdcheck_switch(hyn_226data,enable);
hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0); //soft rst
hyn_wr_reg(hyn_226data,0xD109,2,NULL,0);
break;
case GESTURE_MODE:
hyn_wr_reg(hyn_226data,0xD04C80,3,NULL,0);
break;
case LP_MODE:
break;
case DIFF_MODE:
hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0);
hyn_wr_reg(hyn_226data,0xD10D,2,NULL,0);
break;
case RAWDATA_MODE:
hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0);
hyn_wr_reg(hyn_226data,0xD10A,2,NULL,0);
break;
case FAC_TEST_MODE:
hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0);
hyn_wr_reg(hyn_226data,0xD119,2,NULL,0);
msleep(50); //wait switch to fac mode
break;
case DEEPSLEEP:
hyn_irq_set(hyn_226data,DISABLE);
hyn_wr_reg(hyn_226data,0xD105,2,NULL,0);
break;
case ENTER_BOOT_MODE:
ret |= cst226se_enter_boot();
break;
default :
hyn_esdcheck_switch(hyn_226data,ENABLE);
hyn_226data->work_mode = NOMAL_MODE;
break;
}
return ret;
}
static int cst226se_supend(void)
{
HYN_ENTER();
cst226se_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst226se_resum(void)
{
HYN_ENTER();
cst226se_rst();
msleep(50);
cst226se_set_workmode(NOMAL_MODE,0);
return 0;
}
static void cst226se_rst(void)
{
if(hyn_226data->work_mode==ENTER_BOOT_MODE){
hyn_set_i2c_addr(hyn_226data,MAIN_I2C_ADDR);
}
gpiod_direction_output(hyn_226data->plat_data.reset_gpio,0);
msleep(10);
gpiod_direction_output(hyn_226data->plat_data.reset_gpio,1);
}
static int cst226se_enter_boot(void)
{
int retry = 5,ret = 0;
u8 buf[4] = {0};
hyn_set_i2c_addr(hyn_226data,BOOT_I2C_ADDR);
while(++retry<17){
cst226se_rst();
mdelay(retry);
ret = hyn_wr_reg(hyn_226data,0xA001AA,3,buf,0);
if(ret != 0){
continue;
}
ret = hyn_wr_reg(hyn_226data,0xA003,2,buf,1);
if(ret == 0 && buf[0] == 0x55){
return 0;
}
}
return -1;
}
static int cst226se_updata_tpinfo(void)
{
u8 buf[28];
struct tp_info *ic = &hyn_226data->hw_info;
int ret = 0,retry = 5;
while(--retry){
ret = hyn_wr_reg(hyn_226data,0xD101,2,buf,0);
mdelay(1);
ret |= hyn_wr_reg(hyn_226data,0xD1F4,2,buf,28);
cst226se_set_workmode(NOMAL_MODE,0);
if(ret ==0 && U8TO16(buf[19],buf[18])==0x00a8){
break;
}
msleep(1);
}
if(ret || retry==0){
HYN_ERROR("cst226se_updata_tpinfo failed");
return -1;
}
ic->fw_sensor_txnum = buf[0];
ic->fw_sensor_rxnum = buf[2];
ic->fw_key_num = buf[3];
ic->fw_res_y = (buf[7]<<8)|buf[6];
ic->fw_res_x = (buf[5]<<8)|buf[4];
ic->fw_project_id = (buf[17]<<8)|buf[16];
ic->fw_chip_type = U8TO16(buf[19],buf[18]);
ic->fw_ver = (buf[23]<<24)|(buf[22]<<16)|(buf[21]<<8)|buf[20];
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return 0;
}
static u32 cst226se_read_checksum(void)
{
int ret;
u8 buf[4],retry = 5;
hyn_226data->boot_is_pass = 0;
while(retry--){
ret = hyn_wr_reg(hyn_226data,0xA000,2,buf,1);
if(ret){
mdelay(2);
continue;
}
if(buf[0]!=0) break;
mdelay(2);
}
mdelay(1);
if(buf[0] == 0x01){
memset(buf,0,sizeof(buf));
hyn_wr_reg(hyn_226data,0xA008,2,buf,4);
hyn_226data->boot_is_pass = 1;
}
return U8TO32(buf[3],buf[2],buf[1],buf[0]);
}
static int cst226se_updata_judge(u8 *p_fw, u16 len)
{
u32 f_check_all,f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
int ret = 0;
u8 *p_data = p_fw +7680-12;
struct tp_info *ic = &hyn_226data->hw_info;
f_fw_project_id = U8TO16(p_data[1],p_data[0]);
f_ictype = U8TO16(p_data[3],p_data[2]);
f_fw_ver = U8TO32(p_data[7],p_data[6],p_data[5],p_data[4]);
f_checksum = U8TO32(p_data[11],p_data[10],p_data[9],p_data[8]);
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
ret = cst226se_updata_tpinfo();
if(ret)HYN_ERROR("get tpinfo failed");
//check h file
f_check_all = hyn_sum32(0x55,(u32*)p_fw,(len-4)/4);
if(f_check_all != f_checksum){
HYN_INFO(".h file checksum erro:%04x len:%d",f_check_all,len);
return 0; //not updata
}
if(hyn_226data->boot_is_pass ==0 //emty chip
||(hyn_226data->boot_is_pass && ret) //erro code
|| ( ret == 0 && f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver ) // match new ver .h file
){
return 1; //need updata
}
return 0;
}
static int cst226se_updata_fw(u8 *bin_addr, u16 len)
{
#define CHECKSUM_OFFECT (7680-4)
int i,ret, retry = 4;
u8 i2c_buf[512+2];
u16 eep_addr = 0, total_kbyte = len/512;
u32 fw_checksum = 0;
HYN_ENTER();
if(0 == hyn_226data->fw_file_name[0]){
fw_checksum = U8TO32(bin_addr[CHECKSUM_OFFECT+3],bin_addr[CHECKSUM_OFFECT+2],bin_addr[CHECKSUM_OFFECT+1],bin_addr[CHECKSUM_OFFECT]);
}
else{
ret = hyn_copy_for_updata(hyn_226data,i2c_buf,CHECKSUM_OFFECT,4);
if(ret) goto UPDATA_END;
fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]);
}
hyn_irq_set(hyn_226data,DISABLE);
while(--retry){
ret = cst226se_enter_boot();
if(ret){
HYN_ERROR("cst226se_enter_boot fail");
continue;
}
//start trans fw
for (i=0; i<total_kbyte; i++) {
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x14;
eep_addr = i << 9; //i * 512
i2c_buf[2] = eep_addr;
i2c_buf[3] = eep_addr>>8;
ret = hyn_write_data(hyn_226data, i2c_buf,RW_REG_LEN, 4);
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x18;
if(0 == hyn_226data->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr + eep_addr, 512);
}
else{
ret |= hyn_copy_for_updata(hyn_226data,i2c_buf + 2,eep_addr,512);
}
ret |= hyn_write_data(hyn_226data, i2c_buf,RW_REG_LEN, 514);
ret |= hyn_wr_reg(hyn_226data, 0xA004EE, 3,i2c_buf,0);
msleep(300); //wait finsh
{
uint8_t time_out = 10;
while(--time_out){
ret = hyn_wr_reg(hyn_226data,0xA005,2,i2c_buf,1);
if (ret == 0 && i2c_buf[0] == 0x55){
break;
}
msleep(100);
}
if(time_out==0){
ret = -1;
break;
}
}
}
if(ret) continue;
ret = hyn_wr_reg(hyn_226data,0xA00100,3,i2c_buf,0);
ret |= hyn_wr_reg(hyn_226data,0xA00300,3,i2c_buf,0);
if(ret) continue;
hyn_226data->hw_info.ic_fw_checksum = cst226se_read_checksum();
if(fw_checksum == hyn_226data->hw_info.ic_fw_checksum){
break;
}
}
UPDATA_END:
hyn_set_i2c_addr(hyn_226data,MAIN_I2C_ADDR);
cst226se_rst();
if(fw_checksum == hyn_226data->hw_info.ic_fw_checksum){
mdelay(50);
cst226se_updata_tpinfo();
ret = 0;
HYN_INFO("updata_fw success");
}
else{
ret = -1;
HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_226data->hw_info.ic_fw_checksum);
}
hyn_irq_set(hyn_226data,ENABLE);
return ret;
}
static u32 cst226se_check_esd(void)
{
int ret = 0;
u8 buf[6];
ret = hyn_wr_reg(hyn_226data,0xD040,2,buf,6);
if(ret ==0){
u16 checksum = buf[0]+buf[1]+buf[2]+buf[3]+0xA5;
if(checksum != ( (buf[4]<<8)+ buf[5])){
ret = -1;
}
}
return ret ? 0:(buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24));
}
static int cst226se_get_dbg_data(u8 *buf, u16 len)
{
int ret = -1,timeout=0;
u16 read_len = (hyn_226data->hw_info.fw_sensor_txnum * hyn_226data->hw_info.fw_sensor_rxnum)*2;
u16 total_len = read_len + (hyn_226data->hw_info.fw_sensor_txnum + hyn_226data->hw_info.fw_sensor_rxnum*2 + hyn_226data->hw_info.fw_key_num)*2;
HYN_ENTER();
if(total_len > len){
HYN_ERROR("buf too small");
return -1;
}
timeout = 500;
while(--timeout){ //wait rise edge
if(gpiod_get_value(hyn_226data->plat_data.irq_gpio)==1) break;
mdelay(1);
}
switch(hyn_226data->work_mode){
case DIFF_MODE:
case RAWDATA_MODE:
{
u8 temp[10*16],*ptr;
u16 index = 0,*ptr_dif = (u16*)buf;
ret = hyn_wr_reg(hyn_226data,0x8001,2,buf,total_len); //mt //rx scap //tx scap
memcpy(temp,buf,read_len/2);
ptr = &buf[read_len/2];
for(index = 0;index < read_len/2; index++){
*ptr_dif = ((*ptr<<8)+temp[index]);
ptr++;
ptr_dif++;
}
}
break;
default:
HYN_ERROR("work_mode:%d",hyn_226data->work_mode);
break;
}
return ret==0 ? total_len:-1;
}
#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini"
#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log"
#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST)
static int cst226se_get_test_result(u8 *buf, u16 len)
{
int ret = 0,timeout;
struct tp_info *ic = &hyn_226data->hw_info;
u16 scap_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2;
u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2;
HYN_ENTER();
if((mt_len*3 + scap_len) > len || mt_len==0){
HYN_ERROR("buf too small");
return FAC_GET_DATA_FAIL;
}
msleep(1);
timeout = 500;
while(--timeout){ //wait rise edge
if(gpiod_get_value(hyn_226data->plat_data.irq_gpio)==1) break;
msleep(10);
}
if(hyn_wr_reg(hyn_226data,0x1215,2,buf,mt_len*2+scap_len+4)){ //open high
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read open high failed");
goto selftest_end;
}
{
u16 *test_high = (u16*)&buf[0],*test_low = (u16*)&buf[mt_len],*test_short = (u16*)&buf[mt_len*2],w_tmp = 0,i=0;
for(i=0; i< mt_len/2; i++){
w_tmp = *test_low;
*test_low = *test_high;
*test_high = w_tmp;
test_high++;
test_low++;
}
for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){
*test_short = U16REV((u16)*test_short);
test_short++;
}
}
//read data finlish start test
ret = hyn_factory_multitest(hyn_226data ,FACTEST_PATH, buf,(s16*)(buf+scap_len+mt_len*2),FACTEST_ITEM);
selftest_end:
if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_226data,(s16*)buf,ret,FACTEST_ITEM)){
HYN_INFO("fac_test log save success");
}
cst226se_resum();
return ret;
}
const struct hyn_ts_fuc hyn_cst226se_fuc = {
.tp_rest = cst226se_rst,
.tp_report = cst226se_report,
.tp_supend = cst226se_supend,
.tp_resum = cst226se_resum,
.tp_chip_init = cst226se_init,
.tp_updata_fw = cst226se_updata_fw,
.tp_set_workmode = cst226se_set_workmode,
.tp_check_esd = cst226se_check_esd,
.tp_prox_handle = cst226se_prox_handle,
.tp_get_dbg_data = cst226se_get_dbg_data,
.tp_get_test_result = cst226se_get_test_result
};

View File

@@ -0,0 +1,627 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst3240.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst3240_fw.h"
#define BOOT_I2C_ADDR (0x5A)
#define MAIN_I2C_ADDR (0x5A)
#define RW_REG_LEN (2)
#define MODULE_ID_ADDR (0x3FFC)
#define CST3240_BIN_SIZE (31*512 + 480)
static struct hyn_ts_data *hyn_3240data = NULL;
static const u8 gest_map_tbl[] = {
IDX_NULL, IDX_RIGHT, IDX_UP, IDX_LEFT,
IDX_DOWN, IDX_O, IDX_C, IDX_e,
IDX_M, IDX_M, IDX_W, IDX_V,
IDX_S, IDX_Z, IDX_C, IDX_M,
IDX_M, IDX_e, IDX_S, IDX_e,
IDX_O, IDX_NULL, IDX_NULL, IDX_NULL,
IDX_NULL, IDX_NULL, IDX_NULL, IDX_NULL,
IDX_NULL, IDX_NULL, IDX_NULL, IDX_NULL,
IDX_POWER
};
static int cst3240_updata_judge(u8 *p_fw, u16 len);
static u32 cst3240_read_checksum(void);
static int cst3240_updata_tpinfo(void);
static int cst3240_enter_boot(void);
static u32 cst3240_fread_word(u32 addr);
static void cst3240_rst(void);
static const struct hyn_chip_series hyn_3240_fw[] = {
{0x3240,0x00,"cst32401",(u8*)fw_bin},//default fw
{0x3240,0x01,"cst32402",(u8*)fw_bin},
{0x3240,0x02,"cst32403",(u8*)fw_bin},
{0,0,"",NULL}
};
static int cst3240_init(struct hyn_ts_data* ts_data)
{
int ret = 0,i;
u32 module_id;
HYN_ENTER();
hyn_3240data = ts_data;
ret = cst3240_enter_boot();
if(ret){
HYN_INFO("cst3240_enter_boot failed");
return -1;
}
module_id = cst3240_fread_word(MODULE_ID_ADDR);
hyn_3240data->fw_updata_addr = hyn_3240_fw[0].fw_bin;
for(i = 0; ;i++){
if( hyn_3240_fw[i].moudle_id == module_id){
hyn_3240data->fw_updata_addr = hyn_3240_fw[i].fw_bin;
HYN_INFO("chip %s match fw success",hyn_3240_fw[i].chip_name);
break;
}
if(hyn_3240_fw[i].part_no == 0 && hyn_3240_fw[i].moudle_id == 0){
HYN_INFO("unknown chip or unknown moudle_id use hyn_3240_fw[0]");
break;
}
}
hyn_3240data->hw_info.fw_module_id = module_id;
hyn_3240data->fw_updata_len = CST3240_BIN_SIZE;
hyn_3240data->hw_info.ic_fw_checksum = cst3240_read_checksum();
HYN_INFO("curt read checksum:0x%x module_id:0x%x",hyn_3240data->hw_info.ic_fw_checksum,module_id);
//hyn_wr_reg(hyn_3240data,0xA006EE,3,buf,0); //exit boot
hyn_set_i2c_addr(hyn_3240data,MAIN_I2C_ADDR);
cst3240_rst();
msleep(50);
hyn_3240data->need_updata_fw = cst3240_updata_judge((u8*)fw_bin,CST3240_BIN_SIZE);
return 0;
}
static int cst3240_report(void)
{
u8 buf[80]={0};
u8 finger_num = 0,key_flg = 0,tmp_dat;
int len = 0;
int ret = 0,retry = 2;
switch(hyn_3240data->work_mode){
case NOMAL_MODE:
retry = 2;
while(retry--){
ret = hyn_wr_reg(hyn_3240data,0xD000,2,buf,7);
finger_num = buf[5] & 0x7F;
if(ret || buf[6] != 0xAB || buf[0] == 0xAB || finger_num > MAX_POINTS_REPORT){
ret = -2;
continue;
}
key_flg = (buf[5]&0x80) ? 1:0;
len = 0;
if(finger_num > 1){
len += (finger_num-1)*5;
}
if(key_flg && finger_num){
len += 3;
}
if(len > 0){
ret = hyn_wr_reg(hyn_3240data,0xD007,2,&buf[5],len);
}
if(ret && retry) continue;
ret |= hyn_wr_reg(hyn_3240data,0xD000AB,3,buf,0);
if(ret == 0){
break;
}
}
if(ret){
HYN_ERROR("read frame failed");
break;
}
if(key_flg){ //key
if(hyn_3240data->rp_buf.report_need == REPORT_NONE){
hyn_3240data->rp_buf.report_need |= REPORT_KEY;
}
len = finger_num ? (len+5):3;
hyn_3240data->rp_buf.key_id = (buf[len-2]>>4)-1;
hyn_3240data->rp_buf.key_state = (buf[len-3]&0x0F)==0x03 ? 1:0;
HYN_INFO("key_id:%x state:%x",hyn_3240data->rp_buf.key_id ,hyn_3240data->rp_buf.key_state);
}
if(finger_num){
u16 index = 0,i = 0;
u8 touch_down = 0;
if(hyn_3240data->rp_buf.report_need == REPORT_NONE){
hyn_3240data->rp_buf.report_need |= REPORT_POS;
}
hyn_3240data->rp_buf.rep_num = finger_num;
for(i = 0; i < finger_num; i++){
index = i*5;
hyn_3240data->rp_buf.pos_info[i].pos_id = (buf[index]>>4)&0x0F;
hyn_3240data->rp_buf.pos_info[i].event = (buf[index]&0x0F) == 0x06 ? 1 : 0;
hyn_3240data->rp_buf.pos_info[i].pos_x = ((u16)buf[index + 1]<<4) + ((buf[index + 3] >> 4) & 0x0F);
hyn_3240data->rp_buf.pos_info[i].pos_y = ((u16)buf[index + 2]<<4) + (buf[index + 3] & 0x0F);
hyn_3240data->rp_buf.pos_info[i].pres_z = buf[index + 4];
if(hyn_3240data->rp_buf.pos_info[i].event) touch_down++;
// HYN_INFO("report_id = %d, xy = %d,%d",hyn_3240data->rp_buf.pos_info[i].pos_id,hyn_3240data->rp_buf.pos_info[i].pos_x,hyn_3240data->rp_buf.pos_info[i].pos_y);
}
if(0== touch_down){
hyn_3240data->rp_buf.rep_num = 0;
}
}
break;
case GESTURE_MODE:
ret = hyn_wr_reg(hyn_3240data,0xD04C,2,&tmp_dat,1);
if((tmp_dat&0x7F) <= 32){
tmp_dat = tmp_dat&0x7F;
hyn_3240data->gesture_id = gest_map_tbl[tmp_dat];
hyn_3240data->rp_buf.report_need |= REPORT_GES;
}
break;
default:
break;
}
return ret;
}
static int cst3240_prox_handle(u8 cmd)
{
/*int ret = 0;
switch(cmd){
case 1: //enable
hyn_3240data->prox_is_enable = 1;
hyn_3240data->prox_state = 0;
ret = hyn_wr_reg(hyn_3240data,0xD004B01,3,NULL,0);
break;
case 0: //disable
hyn_3240data->prox_is_enable = 0;
hyn_3240data->prox_state = 0;
ret = hyn_wr_reg(hyn_3240data,0xD004B00,3,NULL,0);
break;
case 2: //read
ret = hyn_wr_reg(hyn_3240data,0xD004B,2,&hyn_3240data->prox_state,1);
break;
}
return ret;*/
return 0;
}
static int cst3240_set_workmode(enum work_mode mode,u8 enable)
{
int ret = 0;
HYN_ENTER();
hyn_3240data->work_mode = mode;
if(mode != NOMAL_MODE)
hyn_esdcheck_switch(hyn_3240data,DISABLE);
switch(mode){
case NOMAL_MODE:
hyn_irq_set(hyn_3240data,ENABLE);
hyn_esdcheck_switch(hyn_3240data,enable);
ret |= hyn_wr_reg(hyn_3240data,0xD109,2,0,0);
break;
case GESTURE_MODE:
ret |= hyn_wr_reg(hyn_3240data,0xD104,2,0,0);
break;
case LP_MODE:
break;
case DIFF_MODE:
ret |= hyn_wr_reg(hyn_3240data,0xD10D,2,0,0);
ret |= hyn_wr_reg(hyn_3240data,0x000500,3,0,0);
break;
case RAWDATA_MODE:
ret |= hyn_wr_reg(hyn_3240data,0xD10A,2,0,0);
ret |= hyn_wr_reg(hyn_3240data,0x000500,3,0,0);
break;
case FAC_TEST_MODE:
cst3240_rst();
msleep(50);
ret |= hyn_wr_reg(hyn_3240data,0xD119,2,0,0);
msleep(50); //wait switch to fac mode
break;
case DEEPSLEEP:
hyn_irq_set(hyn_3240data,DISABLE);
ret |= hyn_wr_reg(hyn_3240data,0xD105,2,0,0);
break;
case ENTER_BOOT_MODE:
ret |= cst3240_enter_boot();
break;
default :
ret = -2;
break;
}
return ret;
}
static int cst3240_supend(void)
{
HYN_ENTER();
cst3240_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst3240_resum(void)
{
HYN_ENTER();
cst3240_rst();
msleep(50);
cst3240_set_workmode(NOMAL_MODE,1);
return 0;
}
static void cst3240_rst(void)
{
if(hyn_3240data->work_mode==ENTER_BOOT_MODE){
hyn_set_i2c_addr(hyn_3240data,MAIN_I2C_ADDR);
}
gpiod_direction_output(hyn_3240data->plat_data.reset_gpio,0);
msleep(8);
gpiod_direction_output(hyn_3240data->plat_data.reset_gpio,1);
}
static int cst3240_enter_boot(void)
{
int retry = 0,ret = 0,times;
u8 buf[4];
hyn_set_i2c_addr(hyn_3240data,BOOT_I2C_ADDR);
while(++retry<20){
cst3240_rst();
mdelay(5+retry);
ret = hyn_wr_reg(hyn_3240data,0xA001AA,3,0,0);
if(ret) continue;
times = 5;
while(--times){
ret = hyn_wr_reg(hyn_3240data,0xA002,2,buf,2);
if(ret ==0 && buf[0] == 0x55 && buf[1] == 0xA8) break;
mdelay(1);
}
if(times == 0) continue;
ret = hyn_wr_reg(hyn_3240data,0xA00100,3,0,0);
if(ret) continue;
break;
}
return retry < 20 ? 0:-1;
}
static int cst3240_updata_tpinfo(void)
{
u8 buf[28];
struct tp_info *ic = &hyn_3240data->hw_info;
int ret = 0,retry = 5;
HYN_ENTER();
while(--retry){
ret = hyn_wr_reg(hyn_3240data,0xD101,2,0,0); //get module info mode
ret |= hyn_wr_reg(hyn_3240data,0xD204,2,buf,8);
ret |= hyn_wr_reg(hyn_3240data,0xD1F4,2,&buf[8],8);
ret |= cst3240_set_workmode(NOMAL_MODE,ENABLE);
if(ret==0 && U8TO16(buf[3],buf[2])==0x3240)break;
mdelay(1);
}
if(ret || retry==0){
HYN_ERROR("cst3240_updata_tpinfo failed");
return -1;
}
ic->fw_project_id = U8TO16(buf[1],buf[0]);
ic->fw_chip_type = U8TO16(buf[3],buf[2]);
ic->fw_ver = U8TO32(buf[7],buf[6],buf[5],buf[4]);
ic->fw_sensor_txnum = buf[8];
ic->fw_sensor_rxnum = buf[10];
ic->fw_key_num = buf[11];
ic->fw_res_y = U8TO16(buf[15],buf[14]);
ic->fw_res_x = U8TO16(buf[13],buf[12]);
HYN_INFO("IC_info tx:%d rx:%d key:%d res-x:%d res-y:%d",ic->fw_sensor_txnum,ic->fw_sensor_rxnum,ic->fw_key_num,ic->fw_res_x,ic->fw_res_y);
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return 0;
}
static u32 cst3240_fread_word(u32 addr)
{
int ret;
u8 rec_buf[4],retry;
u32 read_word = 0;
retry = 3;
while(retry--){
ret = hyn_write_data(hyn_3240data,(u8[]){0xA0,0x18,0x00,0x00,0x00,0x00},2,6);
ret |= hyn_wr_reg(hyn_3240data,0xA01000,3,0,0); //set section
ret |= hyn_wr_reg(hyn_3240data,U8TO32(0xA0,0x0c,(addr&0xFF),((addr>>8)&0xFF)),4,NULL,0); //set addr
ret |= hyn_wr_reg(hyn_3240data,0xA004E4,3,NULL,0); //trig read
if(ret ==0) break;
}
if(ret) return 0;
retry = 10;
while(retry--){
mdelay(2);
ret = hyn_wr_reg(hyn_3240data,0xA018,2,rec_buf,4);
if(ret==0){
read_word = U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0]);
ret = hyn_wr_reg(hyn_3240data,0xA018,2,rec_buf,4);
if(ret == 0 && read_word==U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0])){
break;
}
}
}
return read_word;
}
static u32 cst3240_read_checksum(void)
{
int ret;
u32 check_sum = 0;
u8 buf[4],retry = 6;
hyn_3240data->boot_is_pass = 0;
while(--retry){
ret = hyn_wr_reg(hyn_3240data,0xA000,2,buf,1);
if(ret ==0 && buf[0] == 0x01) break;
mdelay(2);
}
if(retry){
retry = 3;
while(retry){
ret = hyn_wr_reg(hyn_3240data,0xA008,2,buf,4);
if(ret==0){
check_sum = U8TO32(buf[3],buf[2],buf[1],buf[0]);
hyn_3240data->boot_is_pass = 1;
break;
}
mdelay(1);
}
}
return check_sum;
}
static int cst3240_updata_judge(u8 *p_fw, u16 len)
{
int ret;
u32 f_check_all,f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
u8 *p_data; // = p_fw + len- 16;
struct tp_info *ic = &hyn_3240data->hw_info;
HYN_ENTER();
p_data = &p_fw[CST3240_BIN_SIZE-16+4];
f_fw_project_id = U8TO16(p_data[1],p_data[0]);
f_ictype = U8TO16(p_data[3],p_data[2]);
f_fw_ver = U8TO32(p_data[7],p_data[6],p_data[5],p_data[4]);
f_checksum = U8TO32(p_data[11],p_data[10],p_data[9],p_data[8]);
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
ret = cst3240_updata_tpinfo(); //boot checksum pass, communicate failed not updata
if(ret) HYN_ERROR("get tpinfo failed");
f_check_all = hyn_sum32(0x55,(u32*)p_fw,len/4-1);
if(f_check_all != f_checksum){
HYN_INFO(".h file checksum erro:%04x",f_check_all);
return 0; //no need updata
}
if(hyn_3240data->boot_is_pass ==0 //checksum failed
|| ( ret == 0 && f_ictype == ic->fw_chip_type && f_fw_project_id == ic->fw_project_id
&& f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver ) // match new ver .h file
){
return 1; //need updata
}
return 0;
}
static int cst3240_updata_fw(u8 *bin_addr, u16 len)
{
int i,ret=-1, times = 0,retry;
u8 i2c_buf[512+2];
u16 eep_addr = 0;
u32 fw_checksum = 0;
HYN_ENTER();
if(len < CST3240_BIN_SIZE){
HYN_ERROR("len = %d",len);
goto UPDATA_END;
}
// if(len > CST3240_BIN_SIZE) len = CST3240_BIN_SIZE;
if(0 == hyn_3240data->fw_file_name[0]){
fw_checksum = *(u32*)(bin_addr+CST3240_BIN_SIZE-4);
}
else{
ret = hyn_copy_for_updata(hyn_3240data,i2c_buf,CST3240_BIN_SIZE-4,4);
if(ret) goto UPDATA_END;
fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]);
}
hyn_irq_set(hyn_3240data,DISABLE);
hyn_esdcheck_switch(hyn_3240data,DISABLE);
retry = 4;
while(--retry){
hyn_3240data->fw_updata_process = 0;
ret = cst3240_enter_boot();
if(ret) continue;
ret = hyn_wr_reg(hyn_3240data,0xA01000,3,0,0);
if(ret) continue;
//start trans fw
for (i=0; i<32;i++) {
if(31 == i){
hyn_wr_reg(hyn_3240data, 0xA01002, 3,0,0);
hyn_wr_reg(hyn_3240data, 0xA00CE001, 4,0,0);
}
eep_addr = i << 9; //i * 512
ret = hyn_wr_reg(hyn_3240data,0xA0140000+U16REV(eep_addr),4,0,0);
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x18;
if(0 == hyn_3240data->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr + eep_addr, 512);
}else{
ret |= hyn_copy_for_updata(hyn_3240data,i2c_buf + 2,eep_addr,512);
}
ret |= hyn_write_data(hyn_3240data, i2c_buf,RW_REG_LEN, i<31 ? 514:482);
if(ret){ //com erro
continue;
}
ret = hyn_wr_reg(hyn_3240data, 0xA004EE, 3,0,0);
if(ret) ret = hyn_wr_reg(hyn_3240data, 0xA004EE, 3,0,0);
mdelay((4-retry)*100); //wait finsh
times = 100;
while(--times){
ret = hyn_wr_reg(hyn_3240data,0xA005,2,i2c_buf,1);
if(ret==0 && i2c_buf[0] == 0x55) break;
ret = -1;
mdelay(10);
}
if(ret) break;
hyn_3240data->fw_updata_process = i*100/32;
}
// HYN_INFO("ret = %d",ret);
if(ret) continue;
ret = hyn_wr_reg(hyn_3240data,0xA00300,3,i2c_buf,0);
if(ret) continue;
hyn_3240data->hw_info.ic_fw_checksum = cst3240_read_checksum();
HYN_INFO("retry:%d fw_checksum:%x ic_checksum:%x\r\n",4-retry,fw_checksum,hyn_3240data->hw_info.ic_fw_checksum);
if(fw_checksum != hyn_3240data->hw_info.ic_fw_checksum){
ret = -2;
continue;
}
break;
}
UPDATA_END:
hyn_set_i2c_addr(hyn_3240data,MAIN_I2C_ADDR);
cst3240_rst();
if(ret == 0){
msleep(50);
cst3240_updata_tpinfo();
hyn_3240data->fw_updata_process = 100;
HYN_INFO("updata_fw success");
}
else{
hyn_3240data->fw_updata_process |= 0x80;
HYN_ERROR("updata_fw failed");
}
hyn_irq_set(hyn_3240data,ENABLE);
return ret;
}
static u32 cst3240_check_esd(void)
{
int ret = 0;
u8 buf[6];
HYN_ENTER();
ret = hyn_wr_reg(hyn_3240data,0xD040,2,buf,6);
if(ret ==0 && hyn_sum16(0xA5,buf,4)==U8TO16(buf[4],buf[5])){
ret = U8TO32(buf[0],buf[1],buf[2],buf[3]);
}
return ret;
}
static int cst3240_get_dbg_data(u8 *buf, u16 len)
{
int ret = -1,timeout;
u16 read_len = (hyn_3240data->hw_info.fw_sensor_txnum * hyn_3240data->hw_info.fw_sensor_rxnum)*2;
u16 total_len = read_len + (hyn_3240data->hw_info.fw_sensor_txnum + hyn_3240data->hw_info.fw_sensor_rxnum)*2;
HYN_ENTER();
if(total_len > len){
HYN_ERROR("buf too small");
return -1;
}
switch(hyn_3240data->work_mode){
case DIFF_MODE:
case RAWDATA_MODE:
timeout = 60;
while(--timeout){ //wait rise edge
if(gpiod_get_value(hyn_3240data->plat_data.irq_gpio)==1) break;
msleep(1);
}
ret = hyn_wr_reg(hyn_3240data,0x1000,2,buf,read_len); //mt
buf += read_len;
read_len = hyn_3240data->hw_info.fw_sensor_rxnum*2;
ret |= hyn_wr_reg(hyn_3240data,0x7000,2,buf,read_len); //rx
buf += read_len;
read_len = hyn_3240data->hw_info.fw_sensor_txnum*2;
ret |= hyn_wr_reg(hyn_3240data,0x7200,2,buf,read_len); //tx
ret |= hyn_wr_reg(hyn_3240data,0x000500,3,0,0); //end
break;
default:
HYN_ERROR("work_mode:%d",hyn_3240data->work_mode);
break;
}
return ret==0 ? total_len:-1;
}
#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini"
#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log"
#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST)
static int cst3240_get_test_result(u8 *buf, u16 len)
{
int ret = 0,timeout;
struct tp_info *ic = &hyn_3240data->hw_info;
u16 scap_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2;
u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2,i = 0;
u16 *raw_s;
HYN_ENTER();
if((mt_len*3 + scap_len) > len || mt_len==0){
HYN_ERROR("buf too small");
return FAC_GET_DATA_FAIL;
}
msleep(1);
timeout = 500;
while(--timeout){ //wait rise edge
if(gpiod_get_value(hyn_3240data->plat_data.irq_gpio)==1) break;
msleep(10);
}
if(hyn_wr_reg(hyn_3240data,0x3000,2,buf,mt_len)){ //open high
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read open high failed");
goto selftest_end;
}
if(hyn_wr_reg(hyn_3240data,0x1000,2,buf + mt_len,mt_len)){ //open low
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read open low failed");
goto selftest_end;
}
//short test
if(hyn_wr_reg(hyn_3240data,0x5000,2,buf+(mt_len*2),scap_len)){
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read fac short failed");
goto selftest_end;
}
else{
raw_s = (u16*)(buf + mt_len*2);
for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){
*raw_s = U16REV((u16)*raw_s);
raw_s++;
}
}
//read data finlish start test
ret = hyn_factory_multitest(hyn_3240data ,FACTEST_PATH, buf,(s16*)(buf+scap_len+mt_len*2),FACTEST_ITEM);
selftest_end:
if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_3240data,(s16*)buf,ret,FACTEST_ITEM)){
HYN_INFO("fac_test log save success");
}
cst3240_resum();
return ret;
}
const struct hyn_ts_fuc hyn_cst3240_fuc = {
.tp_rest = cst3240_rst,
.tp_report = cst3240_report,
.tp_supend = cst3240_supend,
.tp_resum = cst3240_resum,
.tp_chip_init = cst3240_init,
.tp_updata_fw = cst3240_updata_fw,
.tp_set_workmode = cst3240_set_workmode,
.tp_check_esd = cst3240_check_esd,
.tp_prox_handle = cst3240_prox_handle,
.tp_get_dbg_data = cst3240_get_dbg_data,
.tp_get_test_result = cst3240_get_test_result
};

View File

@@ -0,0 +1,844 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst36xxes.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst36xxes_fw.h"
#define BOOT_I2C_ADDR (0x5A)
#define MAIN_I2C_ADDR (0x58) //use 2 slave addr
#define PART_NO_EN (1)
#define cst36xxes_BIN_SIZE (10*1024)
#define MODULE_ID_ADDR (0x6400)
#define PARTNUM_ADDR (0x7F10)
static struct hyn_ts_data *hyn_36xxesdata = NULL;
static const u8 gest_map_tbl[] = {
IDX_POWER, //GESTURE_LABEL_CLICK,
IDX_POWER, //GESTURE_LABEL_CLICK2,
IDX_UP, //GESTURE_LABEL_TOP,
IDX_DOWN, //GESTURE_LABEL_BOTTOM,
IDX_LEFT, //GESTURE_LABEL_LEFT,
IDX_RIGHT, //GESTURE_LABEL_RIGHT,
IDX_C, //GESTURE_LABEL_C,
IDX_e, //GESTURE_LABEL_E,
IDX_V, //GESTURE_LABEL_v,
IDX_NULL, //GESTURE_LABEL_^,
IDX_NULL, //GESTURE_LABEL_>,
IDX_NULL, //GESTURE_LABEL_<,
IDX_M, //GESTURE_LABEL_M,
IDX_W, //GESTURE_LABEL_W,
IDX_O, //GESTURE_LABEL_O,
IDX_S, //GESTURE_LABEL_S,
IDX_Z, //GESTURE_LABEL_Z
};
static const struct hyn_chip_series hyn_36xxes_fw[] = {
{0xcaca2305,0xffffffff,"cst36xxes",(u8*)fw_bin},
{0,0,"",NULL}
};
static int cst36xxes_updata_judge(u8 *p_fw, u16 len);
static u32 cst36xxes_read_checksum(void);
static int cst36xxes_enter_boot(void);
static u32 cst36xxes_fread_word(u32 addr);
static void cst36xxes_rst(void);
static int cst36xxes_init(struct hyn_ts_data* ts_data)
{
int ret = 0,i;
u32 read_part_no,module_id;
HYN_ENTER();
hyn_36xxesdata = ts_data;
ret = cst36xxes_enter_boot();
if(ret){
HYN_ERROR("cst36xxes_enter_boot failed");
return -1;
}
hyn_36xxesdata->fw_updata_addr = hyn_36xxes_fw[0].fw_bin;
hyn_36xxesdata->fw_updata_len = cst36xxes_BIN_SIZE;
read_part_no = cst36xxes_fread_word(PARTNUM_ADDR);
module_id = cst36xxes_fread_word(MODULE_ID_ADDR);
HYN_INFO("read_part_no:0x%08x module_id:0x%08x",read_part_no,module_id);
if(module_id > 10) module_id = 0xffffffff;
for(i = 0; ;i++){
#if PART_NO_EN
if(hyn_36xxes_fw[i].part_no == read_part_no && hyn_36xxes_fw[i].moudle_id == module_id)
#else
if( hyn_36xxes_fw[i].moudle_id == module_id)
#endif
{ hyn_36xxesdata->fw_updata_addr = hyn_36xxes_fw[i].fw_bin;
HYN_INFO("chip %s match fw success ,partNo check is [%s]",hyn_36xxes_fw[i].chip_name,PART_NO_EN ? "enable":"disable");
break;
}
if(hyn_36xxes_fw[i].part_no == 0 && hyn_36xxes_fw[i].moudle_id == 0){
HYN_INFO("unknown chip or unknown moudle_id use hyn_36xxes_fw[0]");
break;
}
}
hyn_36xxesdata->hw_info.ic_fw_checksum = cst36xxes_read_checksum();
hyn_set_i2c_addr(hyn_36xxesdata,MAIN_I2C_ADDR);
cst36xxes_rst(); //exit boot
mdelay(50);
hyn_36xxesdata->need_updata_fw = cst36xxes_updata_judge(hyn_36xxesdata->fw_updata_addr,cst36xxes_BIN_SIZE);
if(hyn_36xxesdata->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
return 0;
}
static int cst36xxes_report(void)
{
u8 buf[80],i=0;
u8 finger_num = 0,key_num=0,report_typ= 0,key_state=0,key_id = 0,tmp_dat=0;
int ret = 0,retry = 2;
while(retry--){ //read point
ret = hyn_wr_reg(hyn_36xxesdata,0xD0050000,0x80|4,buf,11);
report_typ = buf[4];//FF:pos F0:ges E0:prox
finger_num = buf[5]&0x0f;
key_num = (buf[5]&0xf0)>>4;
if(finger_num+key_num <= MAX_POINTS_REPORT){
if(key_num + finger_num > 1){
ret |= hyn_read_data(hyn_36xxesdata,&buf[11],(key_num + finger_num -1)*5);
}
// if(hyn_sum16(0x55,&buf[6],(key_num + finger_num)*5) != (buf[0] | buf[1]<<8)){
// ret = -1;
// }
}
else{
ret = -2;
}
if(ret && retry) continue;
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,buf,0);
if(ret == 0){
break;
}
}
if(ret) return ret;
if((report_typ==0xff)&&((finger_num+key_num)>0)){
if(key_num){
key_id = buf[10]&0x0f;
key_state = buf[10]>>4;
if(hyn_36xxesdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys
hyn_36xxesdata->rp_buf.report_need |= REPORT_KEY;
}
hyn_36xxesdata->rp_buf.key_id = key_id;
hyn_36xxesdata->rp_buf.key_state = key_state !=0 ? 1:0;
}
if(finger_num){ //pos
u16 index = 0;
u8 touch_down = 0;
if(hyn_36xxesdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys
hyn_36xxesdata->rp_buf.report_need |= REPORT_POS;
}
hyn_36xxesdata->rp_buf.rep_num = finger_num;
for(i = 0; i < finger_num; i++){
index = (key_num+i)*5;
hyn_36xxesdata->rp_buf.pos_info[i].pos_id = buf[index+10]&0x0F;
hyn_36xxesdata->rp_buf.pos_info[i].event = buf[index+10]>>4;
hyn_36xxesdata->rp_buf.pos_info[i].pos_x = buf[index+6] + ((u16)(buf[index+9]&0x0F) <<8); //x is rx direction
hyn_36xxesdata->rp_buf.pos_info[i].pos_y = buf[index+7] + ((u16)(buf[index+9]&0xf0) <<4);
hyn_36xxesdata->rp_buf.pos_info[i].pres_z = buf[index+8];
if(hyn_36xxesdata->rp_buf.pos_info[i].event){
touch_down++;
}
}
if(0== touch_down){
hyn_36xxesdata->rp_buf.rep_num = 0;
}
}
}else if(report_typ == 0xF0){
tmp_dat = buf[10]&0xff;
if((tmp_dat&0x7F) < sizeof(gest_map_tbl) && gest_map_tbl[tmp_dat] != IDX_NULL){
hyn_36xxesdata->gesture_id = gest_map_tbl[tmp_dat];
hyn_36xxesdata->rp_buf.report_need |= REPORT_GES;
HYN_INFO("gesture_id:%d",tmp_dat);
}
}else if(report_typ == 0xE0){//proximity
u8 state = buf[6] ? PS_FAR_AWAY : PS_NEAR;
if(hyn_36xxesdata->prox_is_enable && hyn_36xxesdata->prox_state != state){
hyn_36xxesdata->prox_state = state;
hyn_36xxesdata->rp_buf.report_need |= REPORT_PROX;
}
}
return ret;
}
static int cst36xxes_prox_handle(u8 cmd)
{
int ret = 0;
switch(cmd){
case 1: //enable
hyn_36xxesdata->prox_is_enable = 1;
hyn_36xxesdata->prox_state = 0;
ret = hyn_wr_reg(hyn_36xxesdata,0xD004B001,4,NULL,0);
break;
case 0: //disable
hyn_36xxesdata->prox_is_enable = 0;
hyn_36xxesdata->prox_state = 0;
ret = hyn_wr_reg(hyn_36xxesdata,0xD004B000,4,NULL,0);
break;
default:
break;
}
return ret;
}
static int cst36xxes_set_workmode(enum work_mode mode,u8 enable)
{
int ret = 0;
uint8_t i = 0;
for(i=0;i<5;i++)
{
hyn_wr_reg(hyn_36xxesdata,0xD0000400,4,0,0); //disable lp i2c plu
mdelay(1);
ret = hyn_wr_reg(hyn_36xxesdata,0xD0000400,4,0,0);
if(ret == 0)
break;
}
switch(mode){
case NOMAL_MODE:
hyn_irq_set(hyn_36xxesdata,ENABLE);
hyn_esdcheck_switch(hyn_36xxesdata,enable);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000000,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000C00,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000100,4,0,0);
break;
case GESTURE_MODE:
hyn_esdcheck_switch(hyn_36xxesdata,ENABLE);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000C01,4,0,0);
break;
case LP_MODE:
hyn_esdcheck_switch(hyn_36xxesdata,DISABLE);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00004AB,4,0,0);
break;
case DIFF_MODE:
case RAWDATA_MODE:
case BASELINE_MODE:
case CALIBRATE_MODE:
hyn_esdcheck_switch(hyn_36xxesdata,DISABLE);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00001AB,4,0,0); //enter debug mode
break;
case FAC_TEST_MODE:
hyn_esdcheck_switch(hyn_36xxesdata,DISABLE);
cst36xxes_rst();
msleep(50);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00000AB,4,0,0); //enter fac test
msleep(50); //wait switch to fac mode
break;
case DEEPSLEEP:
hyn_esdcheck_switch(hyn_36xxesdata,DISABLE);
hyn_irq_set(hyn_36xxesdata,DISABLE);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00022AB,4,0,0);
break;
case ENTER_BOOT_MODE:
hyn_esdcheck_switch(hyn_36xxesdata,DISABLE);
ret |= cst36xxes_enter_boot();
break;
case GLOVE_EXIT:
case GLOVE_ENTER:
hyn_36xxesdata->glove_is_enable = mode&0x01;
ret = hyn_wr_reg(hyn_36xxesdata,(mode&0x01)? 0xD0000AAB:0xD0000A00,4,0,0); //glove mode
mode = hyn_36xxesdata->work_mode; //not switch work mode
HYN_INFO("set_glove:%d",hyn_36xxesdata->glove_is_enable);
break;
case CHARGE_EXIT:
case CHARGE_ENTER:
hyn_36xxesdata->charge_is_enable = mode&0x01;
ret = hyn_wr_reg(hyn_36xxesdata,(mode&0x01)? 0xD0000BAB:0xD0000B00,4,0,0); //charg mode
mode = hyn_36xxesdata->work_mode; //not switch work mode
HYN_INFO("set_charge:%d",hyn_36xxesdata->charge_is_enable);
break;
default :
hyn_esdcheck_switch(hyn_36xxesdata,enable);
ret = -2;
break;
}
if(ret != -2){
hyn_36xxesdata->work_mode = mode;
}
HYN_INFO("set_workmode:%d ret:%d",mode,ret);
return ret;
}
static int cst36xxes_supend(void)
{
HYN_ENTER();
cst36xxes_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst36xxes_resum(void)
{
HYN_ENTER();
cst36xxes_rst();
msleep(50);
cst36xxes_set_workmode(NOMAL_MODE,0);
return 0;
}
static void cst36xxes_rst(void)
{
HYN_ENTER();
if(hyn_36xxesdata->work_mode==ENTER_BOOT_MODE){
hyn_set_i2c_addr(hyn_36xxesdata,MAIN_I2C_ADDR);
}
gpiod_direction_output(hyn_36xxesdata->plat_data.reset_gpio,0);
msleep(2);
gpiod_direction_output(hyn_36xxesdata->plat_data.reset_gpio,1);
}
static int cst36xxes_wait_ready(u16 times,u8 ms,u16 reg,u16 check_vlue)
{
int ret = 0;
u8 buf[4];
while(times--){
ret = hyn_wr_reg(hyn_36xxesdata,reg,2,buf,2);
if(0==ret && U8TO16(buf[0],buf[1])==check_vlue){
return 0;
}
mdelay(ms);
}
return -1;
}
static int erase_all_mem(void)
{
int ret = FALSE;
u8 i2c_buf[8];
u32 retry = 3;
u32 Flash_addr;
int i = 0;
for (i=0;i<3;i++){
Flash_addr = 0x2000 + i*0x1000;
ret |= hyn_wr_reg(hyn_36xxesdata,U8TO32(0xA0,0x06,Flash_addr&0xFF,Flash_addr>>8),4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xA0080010,4,0,0); //set len
ret |= hyn_wr_reg(hyn_36xxesdata,0xA00A0100,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xA018CACA,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xA004E0,3,NULL,0); //trig read
mdelay(30);
retry = 20;
while(retry--){
ret = hyn_wr_reg(hyn_36xxesdata,0xA020,2,i2c_buf,2);
if(ret==0 && i2c_buf[0]==0xE0 && i2c_buf[1]==0x88){
break;
}
mdelay(1);
}
}
return TRUE;
}
static int write_code(u8 *bin_addr,uint8_t pak_num)
{
#define PKG_SIZE (512)
u16 eep_addr = 0, eep_len;
u8 i2c_buf[PKG_SIZE+10];
int i = 0;
//start trans fw
// eep_addr = 0;
eep_len = 0;
for (i=0; i<pak_num; i++){
eep_addr = 0x2000+(i<<9);
hyn_wr_reg(hyn_36xxesdata,U8TO32(0xA0,0x06,eep_addr,eep_addr>>8),4,0,0);
hyn_wr_reg(hyn_36xxesdata,0xA0080002,4,0,0);
hyn_wr_reg(hyn_36xxesdata,0xA00A0000,4,0,0);
hyn_wr_reg(hyn_36xxesdata,0xA018CACA,4,0,0);
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x30;
if(0 == hyn_36xxesdata->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr+eep_len, PKG_SIZE);
}else{
hyn_copy_for_updata(hyn_36xxesdata,i2c_buf + 2,eep_len,PKG_SIZE);
}
hyn_write_data(hyn_36xxesdata, i2c_buf,2, PKG_SIZE+2);
hyn_wr_reg(hyn_36xxesdata, 0xA004E1, 3,0,0);
eep_len += PKG_SIZE;
mdelay(20); //wait finsh
cst36xxes_wait_ready(100,1,0xA020,0xE188);
hyn_36xxesdata->fw_updata_process = i*100/pak_num;
}
return TRUE;
}
static int cst36xxes_enter_boot(void)
{
int retry = 0,ret = 0;
hyn_set_i2c_addr(hyn_36xxesdata,BOOT_I2C_ADDR);
while(++retry<20){
cst36xxes_rst();
mdelay(12+retry);
ret = hyn_wr_reg(hyn_36xxesdata,0xA001A7,3,0,0);
if(ret < 0){
continue;
}
if(0==cst36xxes_wait_ready(10,2,0xA002,0x33DD)){
return 0;
}
}
return -1;
}
static int cst36xxes_updata_tpinfo(void)
{
u8 buf[60];
struct tp_info *ic = &hyn_36xxesdata->hw_info;
int ret = 0;
int retry = 5;
while(--retry){
//get all config info
ret |= cst36xxes_set_workmode(NOMAL_MODE,ENABLE);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0010000,0x80|4,buf,50);
if(ret == 0 && buf[3]==0xCA && buf[2]==0xCA) break;
mdelay(1);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000400,4,buf,0);
}
if(ret || retry==0){
HYN_ERROR("cst36xxes_updata_tpinfo failed");
return -1;
}
ic->fw_sensor_txnum = buf[48];
ic->fw_sensor_rxnum = buf[49];
ic->fw_key_num = buf[27];
ic->fw_res_y = (buf[31]<<8)|buf[30];
ic->fw_res_x = (buf[29]<<8)|buf[28];
HYN_INFO("IC_info tx:%d rx:%d key:%d res-x:%d res-y:%d",ic->fw_sensor_txnum,ic->fw_sensor_rxnum,ic->fw_key_num,ic->fw_res_x,ic->fw_res_y);
ic->fw_project_id = U8TO32(buf[39],buf[38],buf[37],buf[36]);
ic->fw_chip_type = U8TO32(buf[3],buf[2],buf[1],buf[0]);
ic->fw_ver = U8TO32(buf[35],buf[34],buf[33],buf[32]);
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return 0;
}
static u32 cst36xxes_fread_word(u32 addr)
{
int ret;
u8 rec_buf[4],retry;
u32 read_word = 0;
retry = 3;
while(retry--){
ret = hyn_wr_reg(hyn_36xxesdata,U8TO32(0xA0,0x06,(addr&0xFF),((addr>>8)&0xFF)),4,NULL,0); //set addr
ret |= hyn_wr_reg(hyn_36xxesdata,0xA0080400,4,0,0); //set len
ret |= hyn_wr_reg(hyn_36xxesdata,0xA00A0000,4,0,0);
ret |= hyn_wr_reg(hyn_36xxesdata,0xA004D2,3,NULL,0); //trig read
if(ret ==0) break;
}
if(ret) return 0;
retry = 20;
while(retry--){
ret = hyn_wr_reg(hyn_36xxesdata,0xA020,2,rec_buf,2);
if(ret==0 && rec_buf[0]==0xD2 && rec_buf[1]==0x88){
ret |= hyn_wr_reg(hyn_36xxesdata,0xA030,2,rec_buf,4);
if(ret ==0){
read_word = U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0]);
break;
}
}
mdelay(1);
}
return read_word;
}
static u32 cst36xxes_read_checksum(void)
{
int ret = -1;
u8 buf[10] = {0};
u32 chipSum = 0;
hyn_36xxesdata->boot_is_pass = 0;
hyn_wr_reg(hyn_36xxesdata,0xA004D6,3,0,0);
mdelay(30);
ret = cst36xxes_wait_ready(20,2,0xA020,0xD688);
ret |= hyn_wr_reg(hyn_36xxesdata,0xA030,2,buf,10);
if(ret == 0 && buf[5] == 0xCA){
chipSum = U8TO32(buf[9],buf[8],buf[7],buf[6]);
hyn_36xxesdata->boot_is_pass = 1;
}
return chipSum;
}
static int cst36xxes_updata_judge(u8 *p_fw, u16 len)
{
u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
// u32 f_check_all;
u8 *p_data = p_fw + 192; //35k
int ret;
struct tp_info *ic = &hyn_36xxesdata->hw_info;
f_fw_project_id = U8TO32(p_data[39],p_data[38],p_data[37],p_data[36]);
f_ictype = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]);
f_fw_ver = U8TO32(p_data[35],p_data[34],p_data[33],p_data[32]);
p_data = p_fw + cst36xxes_BIN_SIZE - 4;
f_checksum = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]);
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
ret = cst36xxes_updata_tpinfo(); //boot checksum pass, communicate failed not updata
if(ret) HYN_ERROR("get tpinfo failed");
if(f_ictype != ic->fw_chip_type || f_fw_project_id != ic->fw_project_id){
HYN_ERROR("not update,please confirm:f_ictype 0x%04x,f_fw_project_id 0x%04x",f_ictype,f_fw_project_id);
return 0; //not updata
}
if(hyn_36xxesdata->boot_is_pass ==0 //boot failed
|| ( ret == 0 && f_ictype == ic->fw_chip_type && f_checksum != ic->ic_fw_checksum && f_fw_ver > ic->fw_ver ) // match new ver .h file
){
return 1; //need updata
}
return 0;
}
static int cst36xxes_updata_fw(u8 *bin_addr, u16 len)
{
#define PKG_SIZE (512)
int ret = -1, retry_fw= 4,pak_num;
u8 i2c_buf[PKG_SIZE+10] , *p_bin_addr;
u32 fw_checksum = 0;
HYN_ENTER();
HYN_INFO("len = %d",len);
hyn_36xxesdata->fw_updata_process = 0;
if(len < cst36xxes_BIN_SIZE){
HYN_ERROR("bin len erro");
goto UPDATA_END;
}
len = cst36xxes_BIN_SIZE-4;
if(0 == hyn_36xxesdata->fw_file_name[0]){
p_bin_addr = bin_addr + len;
fw_checksum = U8TO32(p_bin_addr[3],p_bin_addr[2],p_bin_addr[1],p_bin_addr[0]);
}
else{
ret = hyn_copy_for_updata(hyn_36xxesdata,i2c_buf,cst36xxes_BIN_SIZE,4);
if(ret) goto UPDATA_END;
fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]);
}
HYN_INFO("fw_checksum_all:%04x",fw_checksum);
hyn_irq_set(hyn_36xxesdata,DISABLE);
hyn_esdcheck_switch(hyn_36xxesdata,DISABLE);
len = cst36xxes_BIN_SIZE;
pak_num = len/PKG_SIZE;
while(--retry_fw){
ret = cst36xxes_enter_boot();
if(ret){
HYN_INFO("cst36xxes_enter_boot fail");
continue;
}
ret = erase_all_mem();
if(ret){
HYN_INFO("erase_all_mem fail");
continue;
}
ret = write_code(bin_addr,pak_num);
if (ret){
HYN_INFO("write_code fail");
continue;
}
hyn_36xxesdata->hw_info.ic_fw_checksum = cst36xxes_read_checksum();
HYN_INFO("ic_fw_checksum:%04x",hyn_36xxesdata->hw_info.ic_fw_checksum);
if(fw_checksum == hyn_36xxesdata->hw_info.ic_fw_checksum && 0 != hyn_36xxesdata->boot_is_pass){
break;
}
}
UPDATA_END:
hyn_set_i2c_addr(hyn_36xxesdata,MAIN_I2C_ADDR);
cst36xxes_rst();
if(ret == 0){
msleep(50);
cst36xxes_updata_tpinfo();
hyn_36xxesdata->fw_updata_process = 100;
HYN_INFO("updata_fw success");
}
else{
hyn_36xxesdata->fw_updata_process |= 0x80;
HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_36xxesdata->hw_info.ic_fw_checksum);
}
hyn_irq_set(hyn_36xxesdata,ENABLE);
return ret;
}
static u32 cst36xxes_check_esd(void)
{
int16_t ok = FALSE;
uint8_t i2c_buf[6], retry;
uint8_t flag = 0;
uint32_t esd_value = 0;
retry = 4;
flag = 0;
while (retry--)
{
hyn_wr_reg(hyn_36xxesdata,0xD0190000,4,i2c_buf,0);
udelay(200);
ok = hyn_wr_reg(hyn_36xxesdata,0xD0190000,4,i2c_buf,1);
if (ok == FALSE){
msleep(1);
continue;
} else {
if ((i2c_buf[0] == 0x20) || (i2c_buf[0]==0xA0)){
flag = 1;
esd_value = i2c_buf[0];
break;
} else {
HYN_INFO("ESD data NA: 0x%x ",i2c_buf[0]);
msleep(2);
continue;
}
}
}
HYN_INFO("ESD data:%d,0x%04x,0x%04x", flag, esd_value, hyn_36xxesdata->esd_last_value);
if (flag == 0)
{
hyn_power_source_ctrl(hyn_36xxesdata, 0);
mdelay(2);
hyn_power_source_ctrl(hyn_36xxesdata, 1);
mdelay(2);
cst36xxes_rst();
msleep(40);
esd_value = 0;
hyn_36xxesdata->esd_last_value = 0;
HYN_INFO("esd_check power reset ic");
}
if ((hyn_36xxesdata->work_mode == GESTURE_MODE)&&(esd_value != 0xA0))
{
ok = hyn_wr_reg(hyn_36xxesdata,0xD0000C01,4,0,0);
if (ok == FALSE){
HYN_ERROR("enter_sleep failed");
}
}
hyn_36xxesdata->esd_last_value = esd_value;
return esd_value;
}
static int red_dbg_data(u8 *buf, u16 len ,u32 *cmd_list,u8 type)
{
struct tp_info *ic = &hyn_36xxesdata->hw_info;
int ret = 0;
u16 read_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum)*type;
u16 total_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum + ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*type;
if(total_len > len || read_len == 0){
HYN_ERROR("buf too small or fw_sensor_rxnum fw_sensor_txnum erro");
return -1;
}
ret |= hyn_wr_reg(hyn_36xxesdata,*cmd_list++,0x80|4,buf,read_len); //m cap
buf += read_len;
read_len = ic->fw_sensor_rxnum*type;
ret |= hyn_wr_reg(hyn_36xxesdata,*cmd_list++,0x80|4,buf,read_len); //s rx cap
buf += read_len;
read_len = ic->fw_sensor_txnum*type;
ret |= hyn_wr_reg(hyn_36xxesdata,*cmd_list++,0x80|4,buf,read_len); //s tx cap
// ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); //end
return ret < 0 ? -1:total_len;
}
static int cst36xxes_get_dbg_data(u8 *buf, u16 len)
{
int read_len = -1,ret = 0;
HYN_ENTER();
switch(hyn_36xxesdata->work_mode){
case DIFF_MODE:
read_len = red_dbg_data(buf,len,(u32[]){0xD0090000,0xD0110000,0xD00D0000},2);
break;
case RAWDATA_MODE:
read_len = red_dbg_data(buf,len,(u32[]){0xD0080000,0xD0100000,0xD00C0000},2);
break;
case BASELINE_MODE:
read_len = red_dbg_data(buf,len,(u32[]){0xD00A0000,0xD0120000,0xD00E0000},2);
break;
case CALIBRATE_MODE:{
u16 tmp_len = len/2;
len /= 2;
read_len = red_dbg_data(buf+tmp_len,tmp_len,(u32[]){0xD00B0000,0xD0130000,0xD00F0000},1);
if(read_len > 0){
u8 *src_ptr = buf+tmp_len,tmp;
s16 *des_ptr = (s16*)buf;
tmp_len = read_len;
while(tmp_len--){
tmp = (*src_ptr++)&0x7F;
*des_ptr++ = (tmp & 0x40) ? -(tmp&0x3F):tmp;
}
read_len *= 2;
}
break;
}
default:
HYN_ERROR("work_mode:%d",hyn_36xxesdata->work_mode);
break;
}
// HYN_INFO("read_len:%d len:%d",(int)(sizeof(struct ts_frame)+read_len),len);
if(read_len > 0 && len > (sizeof(struct ts_frame)+read_len)){
ret = cst36xxes_report();
if(ret ==0){
memcpy(buf+read_len+4,(void*)&hyn_36xxesdata->rp_buf,sizeof(struct ts_frame));
read_len += sizeof(struct ts_frame);
}
}
else{
hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); //end
}
return read_len;
}
static int get_fac_test_data(u32 cmd ,u8 *buf, u16 len ,u8 rev)
{
int ret = 0;
ret = hyn_wr_reg(hyn_36xxesdata,cmd,4,0,0);
ret |= hyn_wait_irq_timeout(hyn_36xxesdata,100);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD0090000,0x80|4,buf+rev,len);
ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0);
if(ret==0 && rev){
len /= 2;
while(len--){
*buf = *(buf+2);
buf += 2;
}
}
return ret;
}
#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini"
#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log"
#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST|MULTI_SCAP_TEST)
static int cst36xxes_get_test_result(u8 *buf, u16 len)
{
struct tp_info *ic = &hyn_36xxesdata->hw_info;
u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2;
u16 st_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2;
u8 *rbuf = buf;
u16 *raw_s;
uint8_t i2c_buf[6];
int i = 0;
int ret = FAC_GET_DATA_FAIL;
HYN_ENTER();
if((mt_len*3 + st_len*2 + 4) > len || mt_len==0){
HYN_ERROR("%s", mt_len ? "buf too small":" ic->fw_sensor_rxnum*ic->fw_sensor_txnum=0");
return FAC_GET_DATA_FAIL;
}
if(get_fac_test_data(0xD0002B77,rbuf,mt_len,0)){ //read open high data
HYN_ERROR("read open high failed");
goto TEST_ERRO;
}
rbuf += mt_len;
if(get_fac_test_data(0xD0002B07,rbuf,mt_len,0)){ //read open low data
HYN_ERROR("read open low failed");
goto TEST_ERRO;
}
rbuf += mt_len;
if(get_fac_test_data(0xD0002C00,rbuf,st_len,0)){ //read short test data
HYN_ERROR("read fac short failed");
goto TEST_ERRO;
}
else
{
raw_s = (u16*)(rbuf);
HYN_INFO("raw_s start data = %d",*(raw_s));
for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){
HYN_INFO("short raw data = %d %d",i, *(raw_s+i));
if((*raw_s) != 0) *raw_s = 2000 / (*raw_s);
else *raw_s =0;
HYN_INFO(" data = %d",*(raw_s));
raw_s++;
}
}
//must rest
rbuf += st_len;
cst36xxes_rst();
msleep(20);
ret = hyn_wr_reg(hyn_36xxesdata,0xD00000AB,4,0,0);
if(ret){
HYN_ERROR("exit lowpower scan failed");
return FAC_GET_CFG_FAIL;
}
for (i=0;i<10;i++)
{
ret = hyn_wr_reg(hyn_36xxesdata,0xD0020100,4,i2c_buf,1);
if(ret){
msleep(1);
continue;
}
HYN_INFO("i2c_buf[0] 0x%x", i2c_buf[0]);
if (i2c_buf[0] == 0x30)
break;
msleep(1);
}
if(get_fac_test_data(0xD0002D00,rbuf,st_len,0)){ ///read scap test data
HYN_ERROR("read scap failed");
goto TEST_ERRO;
}
////read data finlish start test
ret = hyn_factory_multitest(hyn_36xxesdata ,FACTEST_PATH, buf,(s16*)(rbuf+st_len),FACTEST_ITEM);
TEST_ERRO:
if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_36xxesdata,(s16*)buf,ret,FACTEST_ITEM)){
HYN_INFO("fac_test log save success");
}
cst36xxes_resum();
return ret;
}
const struct hyn_ts_fuc hyn_cst36xxes_fuc = {
.tp_rest = cst36xxes_rst,
.tp_report = cst36xxes_report,
.tp_supend = cst36xxes_supend,
.tp_resum = cst36xxes_resum,
.tp_chip_init = cst36xxes_init,
.tp_updata_fw = cst36xxes_updata_fw,
.tp_set_workmode = cst36xxes_set_workmode,
.tp_check_esd = cst36xxes_check_esd,
.tp_prox_handle = cst36xxes_prox_handle,
.tp_get_dbg_data = cst36xxes_get_dbg_data,
.tp_get_test_result = cst36xxes_get_test_result
};

View File

@@ -0,0 +1,451 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst3xx.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst3xx_fw.h"
#define BOOT_I2C_ADDR (0x1A)
#define MAIN_I2C_ADDR (0x1A)
#define RW_REG_LEN (2)
#define CST3xx_BIN_SIZE (24*1024 + 24)
#define SOFT_RST_ENABLE (0)
static struct hyn_ts_data *hyn_3xxdata = NULL;
static const u8 gest_map_tbl[33] = {0xff,4,1,3,2,5,12,6,7,7,9,11,10,13,12,7,7,6,10,6,5,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,14};
static int cst3xx_updata_judge(u8 *p_fw, u16 len);
static int cst3xx_read_checksum(u32* check_sum);
static int cst3xx_updata_tpinfo(void);
static int cst3xx_enter_boot(void);
static int cst3xx_set_workmode(enum work_mode mode,u8 enable);
static void cst3xx_rst(void);
static int cst3xx_init(struct hyn_ts_data* ts_data)
{
int ret = 0;
HYN_ENTER();
hyn_3xxdata = ts_data;
ret = cst3xx_enter_boot();
if(ret){
HYN_ERROR("cst3xx_enter_boot failed");
return -1;
}
hyn_3xxdata->fw_updata_addr = (u8*)fw_bin;
hyn_3xxdata->fw_updata_len = CST3xx_BIN_SIZE;
if(0 == cst3xx_read_checksum(&hyn_3xxdata->hw_info.ic_fw_checksum)){
hyn_3xxdata->boot_is_pass = 1;
}
hyn_set_i2c_addr(hyn_3xxdata,MAIN_I2C_ADDR);
cst3xx_rst();
mdelay(50);
hyn_3xxdata->need_updata_fw = cst3xx_updata_judge((u8*)fw_bin,CST3xx_BIN_SIZE);
if(hyn_3xxdata->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
return 0;
}
static int cst3xx_report(void)
{
u8 buf[80];
u8 finger_num = 0,len = 0,write_tail_end = 0,key_state=0,key_id = 0,tmp_dat;
int ret = 0;
hyn_3xxdata->rp_buf.report_need = REPORT_NONE;
switch(hyn_3xxdata->work_mode){
case NOMAL_MODE:
write_tail_end = 1;
ret = hyn_wr_reg(hyn_3xxdata,0xD000,2,buf,7);
len = buf[5] & 0x7F;
if(ret || buf[6] != 0xAB || buf[0] == 0xAB || len > MAX_POINTS_REPORT){
ret = -1;
break;
}
if(buf[5]&0x80){ //key
if(buf[5]==0x80){
key_id = (buf[1]>>4)-1;
key_state = buf[0];
}
else{
// finger_num = len;
len = (len-1)*5+3;
ret = hyn_wr_reg(hyn_3xxdata,0xD007,2,&buf[5],len);
len += 5;
key_id = (buf[len-2]>>4)-1;
key_state = buf[len-3];
}
if(key_state&0x80){
hyn_3xxdata->rp_buf.report_need |= REPORT_KEY;
if((key_id == hyn_3xxdata->rp_buf.key_id || 0 == hyn_3xxdata->rp_buf.key_state)&& key_state == 0x83){
hyn_3xxdata->rp_buf.key_id = key_id;
hyn_3xxdata->rp_buf.key_state = 1;
}
else{
hyn_3xxdata->rp_buf.key_state = 0;
}
}
}
else{ //pos
u16 index = 0;
u8 i = 0;
finger_num = len;
hyn_3xxdata->rp_buf.report_need |= REPORT_POS;
if(finger_num > 1){
len = (len-1)*5 + 1;
ret = hyn_wr_reg(hyn_3xxdata,0xD007,2,&buf[5],len);
}
hyn_3xxdata->rp_buf.rep_num = finger_num;
for(i = 0; i < finger_num; i++){
index = i*5;
hyn_3xxdata->rp_buf.pos_info[i].pos_id = (buf[index]>>4)&0x0F;
hyn_3xxdata->rp_buf.pos_info[i].event = (buf[index]&0x0F) == 0x06 ? 1 : 0;
hyn_3xxdata->rp_buf.pos_info[i].pos_x = ((u16)buf[index + 1]<<4) + ((buf[index + 3] >> 4) & 0x0F);
hyn_3xxdata->rp_buf.pos_info[i].pos_y = ((u16)buf[index + 2]<<4) + (buf[index + 3] & 0x0F);
hyn_3xxdata->rp_buf.pos_info[i].pres_z = buf[index + 4];
// HYN_INFO("report_id = %d, xy = %d,%d",hyn_3xxdata->rp_buf.pos_info[i].pos_id,hyn_3xxdata->rp_buf.pos_info[i].pos_x,hyn_3xxdata->rp_buf.pos_info[i].pos_y);
}
}
break;
case GESTURE_MODE:
ret = hyn_wr_reg(hyn_3xxdata,0xD04C,2,&tmp_dat,1);
if((tmp_dat&0x7F) <= 32){
tmp_dat = tmp_dat&0x7F;
hyn_3xxdata->gesture_id = gest_map_tbl[tmp_dat];
hyn_3xxdata->rp_buf.report_need |= REPORT_GES;
}
break;
default:
break;
}
if(write_tail_end){
hyn_wr_reg(hyn_3xxdata,0xD000AB,3,buf,0);
}
return ret;
}
static int cst3xx_prox_handle(u8 cmd)
{
int ret = 0;
switch(cmd){
case 1: //enable
hyn_3xxdata->prox_is_enable = 1;
hyn_3xxdata->prox_state = 0;
ret = hyn_wr_reg(hyn_3xxdata,0xD004B01,3,NULL,0);
break;
case 0: //disable
hyn_3xxdata->prox_is_enable = 0;
hyn_3xxdata->prox_state = 0;
ret = hyn_wr_reg(hyn_3xxdata,0xD004B00,3,NULL,0);
break;
case 2: //read
ret = hyn_wr_reg(hyn_3xxdata,0xD004B,2,&hyn_3xxdata->prox_state,1);
break;
}
return ret;
}
static int cst3xx_set_workmode(enum work_mode mode,u8 enable)
{
int ret = 0;
hyn_3xxdata->work_mode = mode;
if(mode != NOMAL_MODE)
hyn_esdcheck_switch(hyn_3xxdata,DISABLE);
switch(mode){
case NOMAL_MODE:
hyn_irq_set(hyn_3xxdata,ENABLE);
hyn_esdcheck_switch(hyn_3xxdata,enable);
// hyn_wr_reg(hyn_3xxdata,0xD100,2,NULL,0);
hyn_wr_reg(hyn_3xxdata,0xD109,2,NULL,0);
break;
case GESTURE_MODE:
hyn_wr_reg(hyn_3xxdata,0xD04C80,3,NULL,0);
break;
case LP_MODE:
break;
case DIFF_MODE:
hyn_wr_reg(hyn_3xxdata,0xD10D,2,NULL,0);
break;
case RAWDATA_MODE:
hyn_wr_reg(hyn_3xxdata,0xD10A,2,NULL,0);
break;
case FAC_TEST_MODE:
hyn_wr_reg(hyn_3xxdata,0xD119,2,NULL,0);
break;
case DEEPSLEEP:
hyn_irq_set(hyn_3xxdata,DISABLE);
hyn_wr_reg(hyn_3xxdata,0xD105,2,NULL,0);
break;
case ENTER_BOOT_MODE:
ret |= cst3xx_enter_boot();
break;
default :
hyn_esdcheck_switch(hyn_3xxdata,ENABLE);
hyn_3xxdata->work_mode = NOMAL_MODE;
break;
}
return ret;
}
static int cst3xx_supend(void)
{
HYN_ENTER();
cst3xx_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst3xx_resum(void)
{
HYN_ENTER();
cst3xx_rst();
msleep(50);
cst3xx_set_workmode(NOMAL_MODE,0);
return 0;
}
static void cst3xx_rst(void)
{
if(hyn_3xxdata->work_mode==ENTER_BOOT_MODE){
hyn_set_i2c_addr(hyn_3xxdata,MAIN_I2C_ADDR);
}
#if SOFT_RST_ENABLE
hyn_wr_reg(hyn_3xxdata,0xD10E,2,NULL,0);
#endif
gpiod_direction_output(hyn_3xxdata->plat_data.reset_gpio,0);
msleep(10);
gpiod_direction_output(hyn_3xxdata->plat_data.reset_gpio,1);
}
static int cst3xx_enter_boot(void)
{
int retry = 5,ret = 0;
u8 buf[4] = {0};
hyn_set_i2c_addr(hyn_3xxdata,BOOT_I2C_ADDR);
while(++retry < 17){
cst3xx_rst();
mdelay(retry);
ret = hyn_wr_reg(hyn_3xxdata,0xA001AA,3,buf,0);
if(ret != 0){
continue;
}
ret = hyn_wr_reg(hyn_3xxdata,0xA002,2,buf,1);
if(ret == 0 && (buf[0] == 0xAC || buf[0] == 0x55)){ //ac:3xx 55:1xx
return 0;
}
}
return -1;
}
static int cst3xx_updata_tpinfo(void)
{
u8 buf[28];
struct tp_info *ic = &hyn_3xxdata->hw_info;
int ret = 0;
ret = hyn_wr_reg(hyn_3xxdata,0xD101,2,buf,0);
mdelay(1);
ret |= hyn_wr_reg(hyn_3xxdata,0xD1F4,2,buf,28);
if(ret){
HYN_ERROR("cst3xx_updata_tpinfo failed");
return -1;
}
ic->fw_sensor_txnum = buf[0];
ic->fw_sensor_rxnum = buf[2];
ic->fw_key_num = buf[3];
ic->fw_res_y = (buf[7]<<8)|buf[6];
ic->fw_res_x = (buf[5]<<8)|buf[4];
ic->fw_project_id = (buf[17]<<8)|buf[16];
ic->fw_chip_type = (buf[19]<<8)|buf[18];
ic->fw_ver = (buf[23]<<24)|(buf[22]<<16)|(buf[21]<<8)|buf[20];
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return 0;
}
static int cst3xx_read_checksum(u32* check_sum)
{
int ret;
u8 buf[4],retry = 5;
while(retry--){
ret = hyn_wr_reg(hyn_3xxdata,0xA000,2,buf,1);
if(ret){
mdelay(2);
continue;
}
if(buf[0]!=0) break;
mdelay(2);
}
mdelay(1);
if(buf[0] == 0x01){
memset(buf,0,sizeof(buf));
ret = hyn_wr_reg(hyn_3xxdata,0xA008,2,buf,4);
if(0 == ret){
*check_sum = U8TO32(buf[3],buf[2],buf[1],buf[0]);
return 0;
}
}
return -1;
}
static int cst3xx_updata_judge(u8 *p_fw, u16 len)
{
u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
u8 *p_data = p_fw + len- 16;
struct tp_info *ic = &hyn_3xxdata->hw_info;
f_fw_project_id = U8TO16(p_data[1],p_data[0]);
f_ictype = U8TO16(p_data[3],p_data[2]);
f_fw_ver = U8TO16(p_data[7],p_data[6]);
f_fw_ver = (f_fw_ver<<16)|U8TO16(p_data[5],p_data[4]);
f_checksum = U8TO16(p_data[11],p_data[10]);
f_checksum = (f_checksum << 16)|U8TO16(p_data[9],p_data[8]);
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
cst3xx_updata_tpinfo();
cst3xx_set_workmode(NOMAL_MODE,1);
if(f_ictype != ic->fw_chip_type || f_fw_project_id != ic->fw_project_id){
return 0; //not updata
}
if( hyn_3xxdata->boot_is_pass ==0 //boot failed
||(f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver)){
return 1; //need updata
}
return 0;
}
static int cst3xx_updata_fw(u8 *bin_addr, u16 len)
{
#define CHECKSUM_OFFECT (24*1024+16)
int i,ret, retry = 4;
u8 *i2c_buf;
u16 eep_addr = 0, total_kbyte = 24;
u32 fw_checksum= 0;
HYN_ENTER();
i2c_buf = kmalloc(1024 + 2, GFP_KERNEL);
if(0 == hyn_3xxdata->fw_file_name[0]){
fw_checksum = U8TO32(bin_addr[CHECKSUM_OFFECT+3],bin_addr[CHECKSUM_OFFECT+2],bin_addr[CHECKSUM_OFFECT+1],bin_addr[CHECKSUM_OFFECT]);
}
else{
ret = hyn_copy_for_updata(hyn_3xxdata,i2c_buf,CHECKSUM_OFFECT,4);
if(ret) goto UPDATA_END;
fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]);
}
hyn_irq_set(hyn_3xxdata,DISABLE);
while(--retry){
ret = cst3xx_enter_boot();
if(ret){
HYN_ERROR("cst3xx_enter_boot fail");
continue;
}
ret = hyn_wr_reg(hyn_3xxdata,0xA00200,3,i2c_buf,0);
if(ret) continue;
mdelay(5);
ret = hyn_wr_reg(hyn_3xxdata,0xA003,2,i2c_buf,1);
if(i2c_buf[0] != 0x55)continue;
//start trans fw
for (i=0; i<total_kbyte; i++) {
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x14;
eep_addr = i << 10; //i * 1024
i2c_buf[2] = eep_addr;
i2c_buf[3] = eep_addr>>8;
hyn_write_data(hyn_3xxdata, i2c_buf,RW_REG_LEN, 4);
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x18;
if(0 == hyn_3xxdata->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr + eep_addr, 1024);
}
else{
hyn_copy_for_updata(hyn_3xxdata,i2c_buf + 2,eep_addr,1024);
}
hyn_write_data(hyn_3xxdata, i2c_buf,RW_REG_LEN, 1026);
hyn_wr_reg(hyn_3xxdata, 0xA004EE, 3,i2c_buf,0);
mdelay(60); //wait finsh
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x05;
ret = hyn_wr_reg(hyn_3xxdata,0xA005,2,i2c_buf,1);
if (ret < 0 || i2c_buf[0] != 0x55){
ret = -1;
break;
}
}
if(ret) continue;
ret = hyn_wr_reg(hyn_3xxdata,0xA00300,3,i2c_buf,0);
if(ret) continue;
cst3xx_read_checksum(&hyn_3xxdata->hw_info.ic_fw_checksum);
if(fw_checksum == hyn_3xxdata->hw_info.ic_fw_checksum){
break;
}
}
UPDATA_END:
hyn_set_i2c_addr(hyn_3xxdata,MAIN_I2C_ADDR);
cst3xx_rst();
if(fw_checksum == hyn_3xxdata->hw_info.ic_fw_checksum){
mdelay(50);
cst3xx_updata_tpinfo();
HYN_INFO("updata_fw success");
}
else{
HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_3xxdata->hw_info.ic_fw_checksum);
}
hyn_irq_set(hyn_3xxdata,ENABLE);
kfree(i2c_buf);
return !retry;
}
static u32 cst3xx_check_esd(void)
{
int ret = 0;
u8 buf[6];
ret = hyn_wr_reg(hyn_3xxdata,0xD040,2,buf,6);
if(ret ==0){
u16 checksum = buf[0]+buf[1]+buf[2]+buf[3]+0xA5;
if(checksum != ( (buf[4]<<8)+ buf[5])){
ret = -1;
}
}
return ret ? 0:(buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24));
}
static int cst3xx_get_dbg_data(u8 *buf, u16 len)
{
return 0;
}
static int cst3xx_get_test_result(u8 *buf, u16 len)
{
return 0;
}
const struct hyn_ts_fuc hyn_cst3xx_fuc = {
.tp_rest = cst3xx_rst,
.tp_report = cst3xx_report,
.tp_supend = cst3xx_supend,
.tp_resum = cst3xx_resum,
.tp_chip_init = cst3xx_init,
.tp_updata_fw = cst3xx_updata_fw,
.tp_set_workmode = cst3xx_set_workmode,
.tp_check_esd = cst3xx_check_esd,
.tp_prox_handle = cst3xx_prox_handle,
.tp_get_dbg_data = cst3xx_get_dbg_data,
.tp_get_test_result = cst3xx_get_test_result
};

View File

@@ -0,0 +1,802 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst66xx.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst66xx_fw1.h"
#include "cst66xx_fw2.h"
#define BOOT_I2C_ADDR (0x5A)
#define MAIN_I2C_ADDR (0x58) //use 2 slave addr
#define PART_NO_EN (0)
#define cst66xx_BIN_SIZE (40*1024) //(44*1024) (36*1024)
#define MODULE_ID_ADDR (0xA400)
#define PARTNUM_ADDR (0xFF10)
static struct hyn_ts_data *hyn_66xxdata = NULL;
static const u8 gest_map_tbl[] = {
IDX_POWER, //GESTURE_LABEL_CLICK,
IDX_POWER, //GESTURE_LABEL_CLICK2,
IDX_UP, //GESTURE_LABEL_TOP,
IDX_DOWN, //GESTURE_LABEL_BOTTOM,
IDX_LEFT, //GESTURE_LABEL_LEFT,
IDX_RIGHT, //GESTURE_LABEL_RIGHT,
IDX_C, //GESTURE_LABEL_C,
IDX_e, //GESTURE_LABEL_E,
IDX_V, //GESTURE_LABEL_v,
IDX_NULL, //GESTURE_LABEL_^,
IDX_NULL, //GESTURE_LABEL_>,
IDX_NULL, //GESTURE_LABEL_<,
IDX_M, //GESTURE_LABEL_M,
IDX_W, //GESTURE_LABEL_W,
IDX_O, //GESTURE_LABEL_O,
IDX_S, //GESTURE_LABEL_S,
IDX_Z, //GESTURE_LABEL_Z
};
static const struct hyn_chip_series hyn_6xx_fw[] = {
{0xCACA220E,0xffffffff,"cst3530",(u8*)fw_module1},//if PART_NO_EN==0 use default chip
{0xCACA2202,0xffffffff,"cst3640",(u8*)fw_module1},
{0xCACA2201,0xffffffff,"cst6656",(u8*)fw_module1},
{0xCACA220C,0xffffffff,"cst3548",(u8*)fw_module1},
{0xCACA2209,0xffffffff,"cst3556",(u8*)fw_module1},
{0xCACA2203,0xffffffff,"cst6644",(u8*)fw_module1},
{0xCACA2204,0xffffffff,"cst6856",(u8*)fw_module1},
{0xCACA2204,0x00000002,"cst6856",(u8*)fw_module2},
//0xCACA2205 //154
//0xCACA2206 //148E
{0,0,"",NULL}
};
static int cst66xx_updata_judge(u8 *p_fw, u16 len);
static u32 cst66xx_read_checksum(void);
static int cst66xx_enter_boot(void);
static u32 cst66xx_fread_word(u32 addr);
static void cst66xx_rst(void);
static int cst66xx_init(struct hyn_ts_data* ts_data)
{
int ret = 0,i;
u32 read_part_no,module_id;
HYN_ENTER();
hyn_66xxdata = ts_data;
ret = cst66xx_enter_boot();
if(ret){
HYN_ERROR("cst66xx_enter_boot failed");
return -1;
}
hyn_66xxdata->fw_updata_addr = hyn_6xx_fw[0].fw_bin;
hyn_66xxdata->fw_updata_len = cst66xx_BIN_SIZE;
read_part_no = cst66xx_fread_word(PARTNUM_ADDR);
module_id = cst66xx_fread_word(MODULE_ID_ADDR);
HYN_INFO("read_part_no:0x%08x module_id:0x%08x",read_part_no,module_id);
if(module_id > 10) module_id = 0xffffffff;
for(i = 0; ;i++){
#if PART_NO_EN
if(hyn_6xx_fw[i].part_no == read_part_no && hyn_6xx_fw[i].moudle_id == module_id)
#else
if( hyn_6xx_fw[i].moudle_id == module_id)
#endif
{ hyn_66xxdata->fw_updata_addr = hyn_6xx_fw[i].fw_bin;
HYN_INFO("chip %s match fw success ,partNo check is [%s]",hyn_6xx_fw[i].chip_name,PART_NO_EN ? "enable":"disable");
break;
}
if(hyn_6xx_fw[i].part_no == 0 && hyn_6xx_fw[i].moudle_id == 0){
HYN_INFO("unknown chip or unknown moudle_id use hyn_6xx_fw[0]");
break;
}
}
hyn_66xxdata->hw_info.fw_module_id = module_id;
hyn_66xxdata->hw_info.ic_fw_checksum = cst66xx_read_checksum();
hyn_set_i2c_addr(hyn_66xxdata,MAIN_I2C_ADDR);
cst66xx_rst(); //exit boot
mdelay(50);
hyn_66xxdata->need_updata_fw = cst66xx_updata_judge(hyn_66xxdata->fw_updata_addr,cst66xx_BIN_SIZE);
if(hyn_66xxdata->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
return 0;
}
static int cst66xx_report(void)
{
u8 buf[80],i=0;
u8 finger_num = 0,key_num=0,report_typ= 0,key_state=0,key_id = 0,tmp_dat=0;
int ret = 0,retry = 2;
while(retry--){ //read point
ret = hyn_wr_reg(hyn_66xxdata,0xD0070000,0x80|4,buf,9);
report_typ = buf[2];//FF:pos F0:ges E0:prox
finger_num = buf[3]&0x0f;
key_num = ((buf[3]&0xf0)>>4);
if(finger_num+key_num <= MAX_POINTS_REPORT){
if(key_num + finger_num > 1){
ret |= hyn_read_data(hyn_66xxdata,&buf[9],(key_num + finger_num -1)*5);
}
if(hyn_sum16(0x55,&buf[4],(key_num + finger_num)*5) != (buf[0] | buf[1]<<8)){
ret = -1;
}
}
else{
ret = -2;
}
if(ret && retry) continue;
ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,buf,0);
if(ret == 0){
break;
}
}
if(ret) return ret;
if((report_typ==0xff)&&((finger_num+key_num)>0)){
if(key_num){
key_id = buf[8]&0x0f;
key_state = buf[8]>>4;
if(hyn_66xxdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys
hyn_66xxdata->rp_buf.report_need |= REPORT_KEY;
}
hyn_66xxdata->rp_buf.key_id = key_id;
hyn_66xxdata->rp_buf.key_state = key_state !=0 ? 1:0;
}
if(finger_num){ //pos
u16 index = 0;
u8 touch_down = 0;
if(hyn_66xxdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys
hyn_66xxdata->rp_buf.report_need |= REPORT_POS;
}
hyn_66xxdata->rp_buf.rep_num = finger_num;
for(i = 0; i < finger_num; i++){
index = (key_num+i)*5;
hyn_66xxdata->rp_buf.pos_info[i].pos_id = buf[index+8]&0x0F;
hyn_66xxdata->rp_buf.pos_info[i].event = buf[index+8]>>4;
hyn_66xxdata->rp_buf.pos_info[i].pos_x = buf[index+4] + ((u16)(buf[index+7]&0x0F) <<8); //x is rx direction
hyn_66xxdata->rp_buf.pos_info[i].pos_y = buf[index+5] + ((u16)(buf[index+7]&0xf0) <<4);
hyn_66xxdata->rp_buf.pos_info[i].pres_z = buf[index+6];
if(hyn_66xxdata->rp_buf.pos_info[i].event){
touch_down++;
}
}
if(0== touch_down){
hyn_66xxdata->rp_buf.rep_num = 0;
}
}
}else if(report_typ == 0xF0){ //gesture
tmp_dat = buf[8]&0xff;
if((tmp_dat&0x7F) < sizeof(gest_map_tbl) && gest_map_tbl[tmp_dat] != IDX_NULL){
hyn_66xxdata->gesture_id = gest_map_tbl[tmp_dat];
hyn_66xxdata->rp_buf.report_need |= REPORT_GES;
HYN_INFO("gesture_id:%d",tmp_dat);
}
}else if(report_typ == 0xE0){//proximity
u8 state = buf[4] ? PS_FAR_AWAY : PS_NEAR;
if(hyn_66xxdata->prox_is_enable && hyn_66xxdata->prox_state != state){
hyn_66xxdata->prox_state =state;
hyn_66xxdata->rp_buf.report_need |= REPORT_PROX;
}
}
return ret;
}
static int cst66xx_prox_handle(u8 cmd)
{
int ret = 0;
switch(cmd){
case 1: //enable
hyn_66xxdata->prox_is_enable = 1;
hyn_66xxdata->prox_state = 0xAA;
ret = hyn_wr_reg(hyn_66xxdata,0xD004B001,4,NULL,0);
break;
case 0: //disable
hyn_66xxdata->prox_is_enable = 0;
hyn_66xxdata->prox_state = 0xAA;
ret = hyn_wr_reg(hyn_66xxdata,0xD004B000,4,NULL,0);
break;
default:
break;
}
return ret;
}
static int cst66xx_set_workmode(enum work_mode mode,u8 enable)
{
int ret = 0,i;
for(i=0;i<5;i++){
ret = hyn_wr_reg(hyn_66xxdata,0xD0000400,4,0,0); //disable lp i2c plu
mdelay(1);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0000400,4,0,0);
if(ret == 0)
break;
}
switch(mode){
case NOMAL_MODE:
hyn_irq_set(hyn_66xxdata,ENABLE);
hyn_esdcheck_switch(hyn_66xxdata,ENABLE);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0000000,4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0000C00,4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0000100,4,0,0);
break;
case GESTURE_MODE:
hyn_esdcheck_switch(hyn_66xxdata,ENABLE);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0000C01,4,0,0);
break;
case LP_MODE:
hyn_esdcheck_switch(hyn_66xxdata,DISABLE);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00004AB,4,0,0);
break;
case DIFF_MODE:
case RAWDATA_MODE:
case BASELINE_MODE:
case CALIBRATE_MODE:
hyn_esdcheck_switch(hyn_66xxdata,DISABLE);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00001AB,4,0,0); //enter debug mode
break;
case FAC_TEST_MODE:
hyn_esdcheck_switch(hyn_66xxdata,DISABLE);
cst66xx_rst();
msleep(50);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00000AB,4,0,0); //enter fac test
msleep(50); //wait switch to fac mode
break;
case DEEPSLEEP:
hyn_irq_set(hyn_66xxdata,DISABLE);
hyn_esdcheck_switch(hyn_66xxdata,DISABLE);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00022AB,4,0,0);
break;
case ENTER_BOOT_MODE:
hyn_esdcheck_switch(hyn_66xxdata,DISABLE);
ret |= cst66xx_enter_boot();
break;
case GLOVE_EXIT:
case GLOVE_ENTER:
hyn_66xxdata->glove_is_enable = mode&0x01;
ret = hyn_wr_reg(hyn_66xxdata,(mode&0x01)? 0xD0000AAB:0xD0000A00,4,0,0); //glove mode
mode = hyn_66xxdata->work_mode; //not switch work mode
HYN_INFO("set_glove:%d",hyn_66xxdata->glove_is_enable);
break;
case CHARGE_EXIT:
case CHARGE_ENTER:
hyn_66xxdata->charge_is_enable = mode&0x01;
ret = hyn_wr_reg(hyn_66xxdata,(mode&0x01)? 0xD0000BAB:0xD0000B00,4,0,0); //charg mode
mode = hyn_66xxdata->work_mode; //not switch work mode
HYN_INFO("set_charge:%d",hyn_66xxdata->charge_is_enable);
break;
default :
hyn_esdcheck_switch(hyn_66xxdata,enable);
ret = -2;
break;
}
if(ret != -2){
hyn_66xxdata->work_mode = mode;
}
HYN_INFO("set_workmode:%d ret:%d",mode,ret);
return ret;
}
static int cst66xx_supend(void)
{
HYN_ENTER();
cst66xx_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst66xx_resum(void)
{
HYN_ENTER();
cst66xx_rst();
msleep(50);
cst66xx_set_workmode(NOMAL_MODE,1);
return 0;
}
static void cst66xx_rst(void)
{
HYN_ENTER();
if(hyn_66xxdata->work_mode==ENTER_BOOT_MODE){
hyn_set_i2c_addr(hyn_66xxdata,MAIN_I2C_ADDR);
}
gpiod_direction_output(hyn_66xxdata->plat_data.reset_gpio,0);
msleep(8);
gpiod_direction_output(hyn_66xxdata->plat_data.reset_gpio,1);
}
static int cst66xx_wait_ready(u16 times,u8 ms,u16 reg,u16 check_vlue)
{
int ret = 0;
u8 buf[4];
while(times--){
ret = hyn_wr_reg(hyn_66xxdata,reg,2,buf,2);
if(0==ret && U8TO16(buf[0],buf[1])==check_vlue){
return 0;
}
mdelay(ms);
}
return -1;
}
static int cst66xx_enter_boot(void)
{
int retry = 0,ret = 0;
hyn_set_i2c_addr(hyn_66xxdata,BOOT_I2C_ADDR);
while(++retry<20){
cst66xx_rst();
mdelay(12+retry);
ret = hyn_wr_reg(hyn_66xxdata,0xA001A8,3,0,0);
if(ret < 0){
continue;
}
if(0==cst66xx_wait_ready(10,2,0xA002,0x22DD)){
return 0;
}
}
return -1;
}
static int cst66xx_updata_tpinfo(void)
{
u8 buf[60];
struct tp_info *ic = &hyn_66xxdata->hw_info;
int ret = 0;
int retry = 5;
while(--retry){
//get all config info
ret |= cst66xx_set_workmode(NOMAL_MODE,ENABLE);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0030000,0x80|4,buf,50);
if(ret == 0 && buf[3]==0xCA && buf[2]==0xCA) break;
mdelay(1);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0000400,4,buf,0);
}
if(ret || retry==0){
HYN_ERROR("cst66xx_updata_tpinfo failed");
return -1;
}
ic->fw_sensor_txnum = buf[48];
ic->fw_sensor_rxnum = buf[49];
ic->fw_key_num = buf[27];
ic->fw_res_y = (buf[31]<<8)|buf[30];
ic->fw_res_x = (buf[29]<<8)|buf[28];
HYN_INFO("IC_info tx:%d rx:%d key:%d res-x:%d res-y:%d",ic->fw_sensor_txnum,ic->fw_sensor_rxnum,ic->fw_key_num,ic->fw_res_x,ic->fw_res_y);
ic->fw_project_id = U8TO32(buf[39],buf[38],buf[37],buf[36]);
ic->fw_chip_type = U8TO32(buf[3],buf[2],buf[1],buf[0]);
ic->fw_ver = U8TO32(buf[35],buf[34],buf[33],buf[32]);
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return 0;
}
static u32 cst66xx_fread_word(u32 addr)
{
int ret;
u8 rec_buf[4],retry;
u32 read_word = 0;
retry = 3;
while(retry--){
ret = hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x06,(addr&0xFF),((addr>>8)&0xFF)),4,NULL,0); //set addr
ret |= hyn_wr_reg(hyn_66xxdata,0xA0080400,4,0,0); //set len
ret |= hyn_wr_reg(hyn_66xxdata,0xA00A0300,4,0,0); //?
ret |= hyn_wr_reg(hyn_66xxdata,0xA004D2,3,NULL,0); //trig read
if(ret ==0) break;
}
if(ret) return 0;
retry = 20;
while(retry--){
ret = hyn_wr_reg(hyn_66xxdata,0xA020,2,rec_buf,2);
if(ret==0 && rec_buf[0]==0xD2 && rec_buf[1]==0x88){
ret |= hyn_wr_reg(hyn_66xxdata,0xA040,2,rec_buf,4);
if(ret ==0){
read_word = U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0]);
break;
}
}
mdelay(1);
}
return read_word;
}
static int read_checksum(u16 start_val,u16 start_addr,u16 len ,u32 *check_sum)
{
int ret,retry = 3;
u8 buf[8] = {0};
while(retry--){
ret = hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x06,start_addr&0xFF,start_addr>>8),4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x08,len&0xFF,len>>8),4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x0A,start_val&0xFF,start_val>>8),4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xA004D6,3,0,0);
if(ret) continue;
mdelay(len/0xc00 + 1);
ret = cst66xx_wait_ready(20,2,0xA020,0xD688);
ret |= hyn_wr_reg(hyn_66xxdata,0xA040,2,buf,5);
if(ret == 0 && buf[0] == 0xCA){
*check_sum = U8TO32(buf[4],buf[3],buf[2],buf[1]);
break;
}
else{
ret = -1;
continue;
}
}
return ret ? -1:0;
}
static u32 cst66xx_read_checksum(void)
{
int ret = -1;
u32 chipSum1 = 0,chipSum2 = 0,chipSum3=0,totalSum = 0;
hyn_66xxdata->boot_is_pass = 0;
if(0==read_checksum(0,0,0x9000,&chipSum1)){
if (0==read_checksum(1,0xb000,0x0ffc,&chipSum2)) {
ret = 0;
if (hyn_66xxdata->fw_updata_len >= 44*1024)
ret =read_checksum(1,0xc000,0x0ffc,&chipSum3);
}
}
if(ret ==0){
if (hyn_66xxdata->fw_updata_len >= 44*1024)
totalSum = chipSum1 + chipSum2*2 - 0x55 + chipSum3*2 - 0x55;
else
totalSum = chipSum1 + chipSum2*2 - 0x55;
hyn_66xxdata->boot_is_pass = 1;
}
HYN_INFO("chipSum1:%04x chipSum2:%04x chipSum3:%04x totalSum:%04x",chipSum1,chipSum2,chipSum3,totalSum);
return totalSum;
}
static int cst66xx_updata_judge(u8 *p_fw, u16 len)
{
u32 f_check_all,f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
u8 *p_data;
int ret;
struct tp_info *ic = &hyn_66xxdata->hw_info;
p_data = p_fw + (len >= 44*1024 ? 40*1024:35*1024 );
f_fw_project_id = U8TO32(p_data[39],p_data[38],p_data[37],p_data[36]);
f_ictype = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]);
f_fw_ver = U8TO32(p_data[35],p_data[34],p_data[33],p_data[32]);
p_data = p_fw + (len >= 44*1024 ? 44*1024:40*1024 );
f_checksum = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]);
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
ret = cst66xx_updata_tpinfo(); //boot checksum pass, communicate failed not updata
if(ret) HYN_ERROR("get tpinfo failed");
//check h file
f_check_all = hyn_sum32(0x55,(u32*)p_fw,len/4);
if(f_check_all != f_checksum){
HYN_INFO(".h file checksum erro:%04x len:%d",f_check_all,len);
return 0; //no need updata
}
if(hyn_66xxdata->boot_is_pass ==0 //boot failed
//|| (ret && hyn_66xxdata->boot_is_pass)//erro fw needupdata
|| ( ret == 0 && f_ictype == ic->fw_chip_type && f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver ) // match new ver .h file
){
return 1; //need updata
}
return 0;
}
static int cst66xx_erase_flash(u16 start_addr, u16 len, u16 type)
{
int ret = 0;
// HYN_INFO("addr:%04x len:%04x",0xA0060000+U16REV(start_addr),0xA0080000+U16REV(len));
ret = hyn_wr_reg(hyn_66xxdata,0xA0060000+U16REV(start_addr),4,0,0); //addr
ret |= hyn_wr_reg(hyn_66xxdata,0xA0080000+U16REV(len),4,0,0); //len
ret |= hyn_wr_reg(hyn_66xxdata,0xA00A0000+U16REV(type),4,0,0); //type
ret |= hyn_wr_reg(hyn_66xxdata,0xA018CACA,4,0,0); //key
ret |= hyn_wr_reg(hyn_66xxdata,0xA004E0,3,0,0); //trig
if(ret) return -1;
mdelay(20); //wait finsh earse flash
ret = cst66xx_wait_ready(100,1,0xA020,0xE088);
return ret;
}
static int cst66xx_updata_fw(u8 *bin_addr, u16 len)
{
#define PKG_SIZE (1024)
int i,ret = -1, retry_fw= 4,pak_num;
u8 *i2c_buf , *p_bin_addr;
u16 eep_addr = 0, eep_len;
u32 fw_checksum = 0;
HYN_ENTER();
i2c_buf = kmalloc(PKG_SIZE + 10, GFP_KERNEL);
HYN_INFO("len = %d",len);
hyn_66xxdata->fw_updata_process = 0;
if(len < cst66xx_BIN_SIZE){
HYN_ERROR("bin len erro");
goto UPDATA_END;
}
len = cst66xx_BIN_SIZE;
if(0 == hyn_66xxdata->fw_file_name[0]){
p_bin_addr = bin_addr + len;
fw_checksum = U8TO32(p_bin_addr[3],p_bin_addr[2],p_bin_addr[1],p_bin_addr[0]);
}
else{
ret = hyn_copy_for_updata(hyn_66xxdata,i2c_buf,cst66xx_BIN_SIZE,4);
if(ret) goto UPDATA_END;
fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]);
}
HYN_INFO("fw_checksum_all:%04x",fw_checksum);
hyn_irq_set(hyn_66xxdata,DISABLE);
hyn_esdcheck_switch(hyn_66xxdata,DISABLE);
pak_num = len/PKG_SIZE;
while(--retry_fw){
ret = cst66xx_enter_boot();
if(ret){
HYN_INFO("cst66xx_enter_boot fail");
continue;
}
if(cst66xx_erase_flash(0x0000,0x8000,0x02)) continue; //erase 32k 0x0000~0x8000
if(cst66xx_erase_flash(0x8000,0x1000,0x01)) continue; //erase 4k 0x8000~0x9000
if(cst66xx_erase_flash(0xB000,0x3000,0x04)) continue; //erase 12k 0xB000~0xE000
//start trans fw
eep_addr = 0;
eep_len = 0;
// p_bin_addr = bin_addr;
for (i=0; i<pak_num; i++){
ret = hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x06,eep_addr,eep_addr>>8),4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xA0080004,4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,i>=36 ? 0xA00A0300:0xA00A0000,4,0,0);
ret |= hyn_wr_reg(hyn_66xxdata,0xA018CACA,4,0,0);
if(ret) continue;
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x40;
if(0 == hyn_66xxdata->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr+eep_len, PKG_SIZE);
}else{
ret |= hyn_copy_for_updata(hyn_66xxdata,i2c_buf + 2,eep_len,PKG_SIZE);
}
ret |= hyn_write_data(hyn_66xxdata, i2c_buf,2, PKG_SIZE+2);
msleep(5);
ret |= hyn_wr_reg(hyn_66xxdata, 0xA004E1, 3,0,0);
eep_len += PKG_SIZE;
eep_addr += PKG_SIZE;
if(0x9000 == eep_addr){
eep_addr = 0xB000;
}
mdelay(20); //wait finsh
cst66xx_wait_ready(100,1,0xA020,0xE188);
hyn_66xxdata->fw_updata_process = i*100/pak_num;
// HYN_INFO("FB_%d",hyn_66xxdata->fw_updata_process);
}
if(ret) continue;
hyn_66xxdata->hw_info.ic_fw_checksum = cst66xx_read_checksum();
if(fw_checksum == hyn_66xxdata->hw_info.ic_fw_checksum && 0 != hyn_66xxdata->boot_is_pass){
break;
}
else{
ret = -2;
}
}
UPDATA_END:
hyn_set_i2c_addr(hyn_66xxdata,MAIN_I2C_ADDR);
cst66xx_rst();
if(ret == 0){
msleep(50);
cst66xx_updata_tpinfo();
hyn_66xxdata->fw_updata_process = 100;
HYN_INFO("updata_fw success");
}
else{
hyn_66xxdata->fw_updata_process |= 0x80;
HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_66xxdata->hw_info.ic_fw_checksum);
}
hyn_irq_set(hyn_66xxdata,ENABLE);
kfree(i2c_buf);
return ret;
}
static u32 cst66xx_check_esd(void)
{
int ok = 0;
u8 i2c_buf[6], retry;
u32 esd_value = 0;
retry = 4;
while (retry--){
hyn_wr_reg(hyn_66xxdata,0xD0000D00,4,i2c_buf,0);
udelay(200);
ok = hyn_wr_reg(hyn_66xxdata,0xD0000D00,4,i2c_buf,1);
if((i2c_buf[0] == 0x20 || i2c_buf[0]==0xA0 || i2c_buf[0]==0xA5)&& ok==0){
break;
}
else{
ok = -2;
}
msleep(1);
}
if(-2==ok){ //esdcheck failed rest system
hyn_66xxdata->esd_fail_cnt = 3;
esd_value = hyn_66xxdata->esd_last_value;
}
else if(i2c_buf[0]==0xA5){ //old sdk (V4.5)
ok = hyn_wr_reg(hyn_66xxdata,0xD0040400,4,i2c_buf,4);
if(ok){
mdelay(1);
ok = hyn_wr_reg(hyn_66xxdata,0xD0040400,4,i2c_buf,4);
}
esd_value = ok==0 ? U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]):hyn_66xxdata->esd_last_value;
}
else{
esd_value = hyn_66xxdata->esd_last_value+1;
}
return esd_value;
}
static int red_dbg_data(u8 *buf, u16 len ,u32 *cmd_list,u8 type)
{
struct tp_info *ic = &hyn_66xxdata->hw_info;
int ret = 0;
u16 read_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum)*type;
u16 total_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum + ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*type;
if(total_len > len || read_len == 0){
HYN_ERROR("buf too small or fw_sensor_rxnum fw_sensor_txnum erro");
return -1;
}
ret |= hyn_wr_reg(hyn_66xxdata,*cmd_list++,0x80|4,buf,read_len); //m cap
buf += read_len;
read_len = ic->fw_sensor_rxnum*type;
ret |= hyn_wr_reg(hyn_66xxdata,*cmd_list++,0x80|4,buf,read_len); //s rx cap
buf += read_len;
read_len = ic->fw_sensor_txnum*type;
ret |= hyn_wr_reg(hyn_66xxdata,*cmd_list++,0x80|4,buf,read_len); //s tx cap
// ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); //end
return ret < 0 ? -1:total_len;
}
static int cst66xx_get_dbg_data(u8 *buf, u16 len)
{
int read_len = -1,ret = 0;
HYN_ENTER();
switch(hyn_66xxdata->work_mode){
case DIFF_MODE:
read_len = red_dbg_data(buf,len,(u32[]){0xD0120000,0xD01A0000,0xD0160000},2);
break;
case RAWDATA_MODE:
read_len = red_dbg_data(buf,len,(u32[]){0xD0110000,0xD0190000,0xD0150000},2);
break;
case BASELINE_MODE:
read_len = red_dbg_data(buf,len,(u32[]){0xD0130000,0xD01B0000,0xD0170000},2);
break;
case CALIBRATE_MODE:{
u16 tmp_len = len/2;
len /= 2;
read_len = red_dbg_data(buf+tmp_len,tmp_len,(u32[]){0xD0140000,0xD0180000,0xD01c0000},1);
if(read_len > 0){
u8 *src_ptr = buf+tmp_len,tmp;
s16 *des_ptr = (s16*)buf;
tmp_len = read_len;
while(tmp_len--){
tmp = (*src_ptr++)&0x7F;
*des_ptr++ = (tmp & 0x40) ? -(tmp&0x3F):tmp;
}
read_len *= 2;
}
break;
}
default:
HYN_ERROR("work_mode:%d",hyn_66xxdata->work_mode);
break;
}
// HYN_INFO("read_len:%d len:%d",(int)(sizeof(struct ts_frame)+read_len),len);
if(read_len > 0 && len > (sizeof(struct ts_frame)+read_len)){
ret = cst66xx_report();
if(ret ==0){
memcpy(buf+read_len+4,(void*)&hyn_66xxdata->rp_buf,sizeof(struct ts_frame));
read_len += sizeof(struct ts_frame);
}
}
else{
hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); //end
}
return read_len;
}
static int get_fac_test_data(u32 cmd ,u8 *buf, u16 len ,u8 rev)
{
int ret = 0;
ret = hyn_wr_reg(hyn_66xxdata,cmd,4,0,0);
ret |= hyn_wait_irq_timeout(hyn_66xxdata,100);
ret |= hyn_wr_reg(hyn_66xxdata,0xD0120000,0x80|4,buf+rev,len);
ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0);
if(ret==0 && rev){
len /= 2;
while(len--){
*buf = *(buf+2);
buf += 2;
}
}
return ret;
}
#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini"
#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log"
#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST|MULTI_SCAP_TEST)
static int cst66xx_get_test_result(u8 *buf, u16 len)
{
struct tp_info *ic = &hyn_66xxdata->hw_info;
u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2;
u16 st_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2;
u8 *rbuf = buf;
int ret = FAC_GET_DATA_FAIL;
HYN_ENTER();
if((mt_len*3 + st_len*2 + 4) > len || mt_len==0){
HYN_ERROR("%s", mt_len ? "buf too small":" ic->fw_sensor_rxnum*ic->fw_sensor_txnum=0");
return FAC_GET_DATA_FAIL;
}
if(get_fac_test_data(0xD0002000,rbuf,mt_len,0)){ //read open high data
HYN_ERROR("read open high failed");
goto TEST_ERRO;
}
rbuf += mt_len;
if(get_fac_test_data(0xD0002100,rbuf,mt_len,0)){ //read open low data
HYN_ERROR("read open low failed");
goto TEST_ERRO;
}
rbuf += mt_len;
if(get_fac_test_data(0xD0002300,rbuf,st_len,1)){ //read short test data
HYN_ERROR("read fac short failed");
goto TEST_ERRO;
}
//must rest
rbuf += st_len;
if(get_fac_test_data(0xD0002500,rbuf,st_len,0)){ ///read scap test data
HYN_ERROR("read scap failed");
goto TEST_ERRO;
}
////read data finlish start test
ret = hyn_factory_multitest(hyn_66xxdata ,FACTEST_PATH, buf,(s16*)(rbuf+st_len),FACTEST_ITEM);
TEST_ERRO:
if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_66xxdata,(s16*)buf,ret,FACTEST_ITEM)){
HYN_INFO("fac_test log save success");
}
cst66xx_resum();
return ret;
}
const struct hyn_ts_fuc hyn_cst66xx_fuc = {
.tp_rest = cst66xx_rst,
.tp_report = cst66xx_report,
.tp_supend = cst66xx_supend,
.tp_resum = cst66xx_resum,
.tp_chip_init = cst66xx_init,
.tp_updata_fw = cst66xx_updata_fw,
.tp_set_workmode = cst66xx_set_workmode,
.tp_check_esd = cst66xx_check_esd,
.tp_prox_handle = cst66xx_prox_handle,
.tp_get_dbg_data = cst66xx_get_dbg_data,
.tp_get_test_result = cst66xx_get_test_result
};

View File

@@ -0,0 +1,544 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst7xx.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst7xx_fw.h"
#define CUSTOM_SENSOR_NUM (20)
#define BOOT_I2C_ADDR (0x6A)
#define MAIN_I2C_ADDR (0x15)
#define RW_REG_LEN (2)
#define CST7XX_BIN_SIZE (15*1024)
static struct hyn_ts_data *hyn_7xxdata = NULL;
static int cst7xx_updata_judge(u8 *p_fw, u16 len);
static u32 cst7xx_read_checksum(void);
static int cst7xx_updata_tpinfo(void);
static int cst7xx_enter_boot(void);
static int cst7xx_set_workmode(enum work_mode mode,u8 enable);
static void cst7xx_rst(void);
static int cst7xx_init(struct hyn_ts_data* ts_data)
{
int ret = 0;
u8 buf[4];
HYN_ENTER();
hyn_7xxdata = ts_data;
ret = cst7xx_enter_boot();
if(ret == FALSE){
HYN_ERROR("cst7xx_enter_boot failed");
return FALSE;
}
hyn_7xxdata->fw_updata_addr = (u8*)fw_bin;
hyn_7xxdata->fw_updata_len = CST7XX_BIN_SIZE;
hyn_7xxdata->hw_info.ic_fw_checksum = cst7xx_read_checksum();
hyn_wr_reg(hyn_7xxdata,0xA006EE,3,buf,0); //exit boot
cst7xx_rst();
mdelay(50);
hyn_set_i2c_addr(hyn_7xxdata,MAIN_I2C_ADDR);
cst7xx_updata_tpinfo();
cst7xx_set_workmode(NOMAL_MODE,0);
hyn_7xxdata->need_updata_fw = cst7xx_updata_judge((u8*)fw_bin,CST7XX_BIN_SIZE);
if(hyn_7xxdata->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
return TRUE;
}
static int cst7xx_enter_boot(void)
{
uint8_t t;
hyn_set_i2c_addr(hyn_7xxdata,BOOT_I2C_ADDR);
for (t = 5;; t += 2)
{
int ok = FALSE;
uint8_t i2c_buf[4] = {0};
if (t >= 15){
return FALSE;
}
cst7xx_rst();
mdelay(t);
ok = hyn_wr_reg(hyn_7xxdata, 0xA001AA, 3, i2c_buf, 0);
if(ok == FALSE){
continue;
}
ok = hyn_wr_reg(hyn_7xxdata, 0xA003, 2, i2c_buf, 1);
if(ok == FALSE){
continue;
}
if (i2c_buf[0] != 0x55){
continue;
}
break;
}
return TRUE;
}
static int write_code(u8 *bin_addr,uint8_t retry)
{
uint16_t i,t;//,j;
int ok = FALSE;
u8 i2c_buf[512+2];
bin_addr+=6;
hyn_7xxdata->fw_updata_process = 0;
for ( i = 0;i < CST7XX_BIN_SIZE; i += 512)
{
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x14;
i2c_buf[2] = i;
i2c_buf[3] = i >> 8;
ok = hyn_write_data(hyn_7xxdata, i2c_buf,RW_REG_LEN, 4);
if (ok == FALSE){
break;
}
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x18;
if(0 == hyn_7xxdata->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr + i, 512);
}
else{
ok = hyn_copy_for_updata(hyn_7xxdata,i2c_buf + 2,i+6,512);
if(ok)break;
}
ok = hyn_write_data(hyn_7xxdata, i2c_buf,RW_REG_LEN, 514);
if (ok == FALSE){
break;
}
ok = hyn_wr_reg(hyn_7xxdata, 0xA004EE, 3,i2c_buf,0);
if (ok == FALSE){
break;
}
mdelay(100 * retry);
hyn_7xxdata->fw_updata_process = i*100/CST7XX_BIN_SIZE;
for (t = 0;; t ++)
{
if (t >= 50){
return FALSE;
}
mdelay(5);
ok = hyn_wr_reg(hyn_7xxdata,0xA005,2,i2c_buf,1);
if (ok == FALSE){
continue;
}
if (i2c_buf[0] != 0x55){
continue;
}
break;
}
}
return ok;
}
static uint32_t cst7xx_read_checksum(void)
{
int ret = -1,time_out,retry = 3;
uint8_t i2c_buf[4] = {0};
uint32_t value = 0;
hyn_7xxdata->boot_is_pass = 0;
while(retry--){
ret = hyn_wr_reg(hyn_7xxdata, 0xA00300, 3, i2c_buf, 0);
if(ret) continue;
mdelay(100);
time_out = 100;
while(time_out--){
mdelay(10);
ret = hyn_wr_reg(hyn_7xxdata, 0xA000, 2, i2c_buf, 1);
if(0==ret && i2c_buf[0] == 1){
hyn_7xxdata->boot_is_pass = 1;
break;
}
ret = -2;
}
if(ret) continue;
ret = hyn_wr_reg(hyn_7xxdata, 0xA008, 2, i2c_buf, 2);
if(ret == 0){
value = (i2c_buf[1]<<8)|i2c_buf[0];
break;
}
}
return value;
}
static int cst7xx_updata_fw(u8 *bin_addr, u16 len)
{
int retry = 0;
int ok = FALSE,ret = 0;
u8 i2c_buf[4];
u32 fw_checksum = 0;
// len = len;
HYN_ENTER();
if(0 == hyn_7xxdata->fw_file_name[0]){
fw_checksum =U8TO16(bin_addr[5],bin_addr[4]);
}
else{
ok = hyn_copy_for_updata(hyn_7xxdata,i2c_buf,4,2);
if(ok) goto UPDATA_END;
fw_checksum = U8TO16(i2c_buf[1],i2c_buf[0]);
}
hyn_irq_set(hyn_7xxdata,DISABLE);
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
for(retry = 1; retry<10; retry++){
ret = -1;
ok = cst7xx_enter_boot();
if (ok == FALSE){
continue;
}
ok = write_code(bin_addr,retry);
if (ok == FALSE){
continue;
}
hyn_7xxdata->hw_info.ic_fw_checksum = cst7xx_read_checksum();
if(fw_checksum != hyn_7xxdata->hw_info.ic_fw_checksum && hyn_7xxdata->boot_is_pass){
hyn_7xxdata->fw_updata_process |= 0x80;
continue;
}
hyn_7xxdata->fw_updata_process = 100;
ret = 0;
break;
}
UPDATA_END:
hyn_wr_reg(hyn_7xxdata,0xA006EE,3,i2c_buf,0); //exit boot
mdelay(2);
cst7xx_rst();
mdelay(50);
hyn_set_i2c_addr(hyn_7xxdata,MAIN_I2C_ADDR);
HYN_INFO("updata_fw %s",ret == 0 ? "success" : "failed");
if(ret == 0){
cst7xx_updata_tpinfo();
}
hyn_irq_set(hyn_7xxdata,ENABLE);
hyn_esdcheck_switch(hyn_7xxdata,ENABLE);
return ret;
}
static int cst7xx_updata_tpinfo(void)
{
u8 buf[8];
struct tp_info *ic = &hyn_7xxdata->hw_info;
int ret = 0;
ret = hyn_wr_reg(hyn_7xxdata,0xA6,1,buf,6);
if(ret == FALSE){
HYN_ERROR("cst7xx_updata_tpinfo failed");
return FALSE;
}
ic->fw_sensor_txnum = 2;
ic->fw_sensor_rxnum = CUSTOM_SENSOR_NUM;
ic->fw_key_num = hyn_7xxdata->plat_data.key_num;
ic->fw_res_y = hyn_7xxdata->plat_data.y_resolution;
ic->fw_res_x = hyn_7xxdata->plat_data.x_resolution;
ic->fw_project_id = buf[3];
ic->fw_chip_type = buf[4];
ic->fw_ver = buf[0];
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return TRUE;
}
static int cst7xx_updata_judge(u8 *p_fw, u16 len)
{
u32 f_checksum,f_fw_ver,f_ictype,f_project_id;//f_module_id;
u8 *p_data = p_fw ;
u16 i,check_h =0x55;
struct tp_info *ic = &hyn_7xxdata->hw_info;
f_checksum = U8TO16(p_data[5],p_data[4]);
p_data += (0x3BF8+6);
f_project_id = p_data[2];
f_ictype = (p_data[1]<<8)|p_data[0];
f_fw_ver = (p_data[5]<<8)|p_data[4];
// f_module_id = p_data[3];
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_project_id,f_ictype,f_fw_ver,f_checksum);
p_data = p_fw+6;
for(i=0;i<len-2;i++){
u16 tmp;
check_h += p_data[i];
tmp = check_h>>15;
check_h <<= 1;
check_h |= tmp;
}
if(check_h != f_checksum){
HYN_ERROR(".h file is damaged !! check_h:0x%04x f_checksum:0x%04x",check_h,f_checksum);
return 0;
}
if(hyn_7xxdata->boot_is_pass==0 //emty
|| (ic->fw_ver <= f_fw_ver && ic->fw_project_id ==f_project_id && f_checksum != ic->ic_fw_checksum)
){
return 1; //need updata
}
return 0;
}
//------------------------------------------------------------------------------//
static int cst7xx_set_workmode(enum work_mode mode,u8 enable)
{
int ret = -1;
switch(mode){
case NOMAL_MODE:
hyn_esdcheck_switch(hyn_7xxdata,ENABLE);
hyn_irq_set(hyn_7xxdata,ENABLE);
ret = hyn_wr_reg(hyn_7xxdata,0xFE00,2,NULL,0);
break;
case GESTURE_MODE:
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
ret = hyn_wr_reg(hyn_7xxdata,0xD001,2,NULL,0);
break;
case LP_MODE:
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
break;
case DIFF_MODE:
case RAWDATA_MODE:
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
ret = hyn_wr_reg(hyn_7xxdata,mode==DIFF_MODE ? 0xBF07:0xBF06,2,NULL,0);
break;
case FAC_TEST_MODE:
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
hyn_wr_reg(hyn_7xxdata,0xF001,2,NULL,0);
msleep(50);
break;
case DEEPSLEEP:
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
hyn_irq_set(hyn_7xxdata,DISABLE);
ret = hyn_wr_reg(hyn_7xxdata,0xA503,2,NULL,0);
break;
case ENTER_BOOT_MODE:
hyn_esdcheck_switch(hyn_7xxdata,DISABLE);
ret |= cst7xx_enter_boot();
break;
case CHARGE_EXIT:
case CHARGE_ENTER:
hyn_7xxdata->charge_is_enable = mode&0x01;
ret = hyn_wr_reg(hyn_7xxdata,(mode&0x01)? 0xE601:0xE600,2,0,0); //charg mode
mode = hyn_7xxdata->work_mode; //not switch work mode
break;
default :
hyn_esdcheck_switch(hyn_7xxdata,enable);
hyn_7xxdata->work_mode = NOMAL_MODE;
ret = -2;
break;
}
if(ret != -2){
hyn_7xxdata->work_mode = mode;
}
return ret;
}
static int cst7xx_prox_handle(u8 cmd)
{
int ret = 0;
switch(cmd){
case 1: //enable
hyn_7xxdata->prox_is_enable = 1;
hyn_7xxdata->prox_state = 0;
ret = hyn_wr_reg(hyn_7xxdata,0xB001,2,NULL,0);
break;
case 0: //disable
hyn_7xxdata->prox_is_enable = 0;
hyn_7xxdata->prox_state = 0;
ret = hyn_wr_reg(hyn_7xxdata,0xB000,2,NULL,0);
break;
default:
break;
}
return ret;
}
static void cst7xx_rst(void)
{
if(hyn_7xxdata->work_mode==ENTER_BOOT_MODE){
hyn_set_i2c_addr(hyn_7xxdata,MAIN_I2C_ADDR);
}
gpiod_direction_output(hyn_7xxdata->plat_data.reset_gpio,0);
msleep(10);
gpiod_direction_output(hyn_7xxdata->plat_data.reset_gpio,1);
}
static int cst7xx_supend(void)
{
HYN_ENTER();
cst7xx_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst7xx_resum(void)
{
cst7xx_rst();
msleep(50);
cst7xx_set_workmode(NOMAL_MODE,0);
return 0;
}
static int cst7xx_report(void)
{
uint8_t i = 0;
uint8_t i2c_buf[3+6*MAX_POINTS_REPORT] = {0};
uint8_t id = 0,index = 0;
struct hyn_plat_data *dt = &hyn_7xxdata->plat_data;
memset(&hyn_7xxdata->rp_buf,0,sizeof(hyn_7xxdata->rp_buf));
hyn_7xxdata->rp_buf.report_need = REPORT_NONE;
if(hyn_7xxdata->work_mode == GESTURE_MODE){
static const uint8_t ges_map[][2] = {{0x24,IDX_POWER},{0x22,IDX_UP},{0x23,IDX_DOWN},{0x20,IDX_LEFT},{0x21,IDX_RIGHT},
{0x34,IDX_C},{0x33,IDX_e},{0x32,IDX_M},{0x30,IDX_O},{0x46,IDX_S},{0x54,IDX_V},{0x31,IDX_W},{0x65,IDX_Z}};
if(hyn_wr_reg(hyn_7xxdata,0xD3,1,i2c_buf,1)){
goto FAILD_END;
}
index = sizeof(ges_map)/2;
hyn_7xxdata->gesture_id = IDX_NULL;
for(i=0; i<index; i++){
if(ges_map[i][0] == i2c_buf[0]){
hyn_7xxdata->gesture_id = ges_map[i][1];
hyn_7xxdata->rp_buf.report_need = REPORT_GES;
break;
}
}
return TRUE;
}
else{
int ret = -1,retry = 3;
u8 event = 0;
while(--retry){
ret = hyn_wr_reg(hyn_7xxdata,0x00,1,i2c_buf,(3+6*2));
if(ret == 0 && i2c_buf[2] < 3) break;
ret = -1;
}
if(ret){
goto FAILD_END;
}
if(hyn_7xxdata->prox_is_enable){
u8 state=0;
if(i2c_buf[1]==0xE0 || i2c_buf[1]==0){
state = PS_FAR_AWAY;
}
else if(i2c_buf[1]==0xC0){
state = PS_NEAR;
}
if(hyn_7xxdata->prox_state != state){
hyn_7xxdata->prox_state = state;
hyn_7xxdata->rp_buf.report_need |= REPORT_PROX;
}
}
hyn_7xxdata->rp_buf.rep_num = i2c_buf[2]&0x0F;
for(i = 0 ; i < 2 ; i++){
id = (i2c_buf[5 + i*6] & 0xf0)>>4;
event = i2c_buf[3 + i*6]&0xC0;
if(id > 1 || event==0xC0) continue;
hyn_7xxdata->rp_buf.pos_info[index].pos_id = id;
hyn_7xxdata->rp_buf.pos_info[index].event = 0x40 == event ? 0:1;
hyn_7xxdata->rp_buf.pos_info[index].pos_x = ((u16)(i2c_buf[3 + i*6] & 0x0f)<<8) + i2c_buf[4 + i*6];
hyn_7xxdata->rp_buf.pos_info[index].pos_y = ((u16)(i2c_buf[5 + i*6] & 0x0f)<<8) + i2c_buf[6 + i*6];
// hyn_7xxdata->rp_buf.pos_info[index].pres_z = (i2c_buf[7 + i*6] <<8) + i2c_buf[8 + i*6] ;
hyn_7xxdata->rp_buf.pos_info[index].pres_z = 3+(hyn_7xxdata->rp_buf.pos_info[index].pos_x&0x03); //press mast chang
index++;
}
if(index){
hyn_7xxdata->rp_buf.report_need |= REPORT_POS;
}
if(dt->key_num){
i = dt->key_num;
while(i){
i--;
if(dt->key_y_coords ==hyn_7xxdata->rp_buf.pos_info[0].pos_y && dt->key_x_coords[i] == hyn_7xxdata->rp_buf.pos_info[0].pos_x){
hyn_7xxdata->rp_buf.key_id = i;
hyn_7xxdata->rp_buf.key_state = hyn_7xxdata->rp_buf.pos_info[0].event;
hyn_7xxdata->rp_buf.report_need = REPORT_KEY;
}
}
}
}
return TRUE;
FAILD_END:
HYN_ERROR("read report data failed");
return FALSE;
}
static u32 cst7xx_check_esd(void)
{
int ret = -1;
u8 buf[4];
ret = hyn_wr_reg(hyn_7xxdata,0xAE,1,buf,2);
return ret ? -1:U8TO16(buf[1],buf[0]);
}
static int cst7xx_get_dbg_data(u8 *buf, u16 len)
{
int ret = -1,read_len = len;
switch (hyn_7xxdata->work_mode){
case DIFF_MODE:
ret = hyn_wr_reg(hyn_7xxdata, 0x41, 1,buf,read_len);
break;
case RAWDATA_MODE:
ret = hyn_wr_reg(hyn_7xxdata, 0x61, 1,buf,read_len);
break;
default:
HYN_ERROR("work_mode:%d",hyn_7xxdata->work_mode);
break;
}
return ret==0 ? read_len:-1;
}
static int cst7xx_get_test_result(u8 *buf, u16 len)
{
return 0;
}
const struct hyn_ts_fuc hyn_cst7xx_fuc = {
.tp_rest = cst7xx_rst,
.tp_report = cst7xx_report,
.tp_supend = cst7xx_supend,
.tp_resum = cst7xx_resum,
.tp_chip_init = cst7xx_init,
.tp_updata_fw = cst7xx_updata_fw,
.tp_set_workmode = cst7xx_set_workmode,
.tp_check_esd = cst7xx_check_esd,
.tp_prox_handle = cst7xx_prox_handle,
.tp_get_dbg_data = cst7xx_get_dbg_data,
.tp_get_test_result = cst7xx_get_test_result
};

View File

@@ -0,0 +1,518 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst8xxT.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst8xxT_fw.h"
#define CUSTOM_SENSOR_NUM (10)
#define BOOT_I2C_ADDR (0x6A)
#define MAIN_I2C_ADDR (0x15)
#define RW_REG_LEN (2)
#define CST8xxT_BIN_SIZE (15*1024)
static struct hyn_ts_data *hyn_8xxTdata = NULL;
static int cst8xxT_updata_judge(u8 *p_fw, u16 len);
static u32 cst8xxT_read_checksum(void);
static int cst8xxT_updata_tpinfo(void);
static int cst8xxT_enter_boot(void);
static int cst8xxT_set_workmode(enum work_mode mode,u8 enable);
static void cst8xxT_rst(void);
static int cst8xxT_init(struct hyn_ts_data* ts_data)
{
int ret = 0;
u8 buf[4];
HYN_ENTER();
hyn_8xxTdata = ts_data;
ret = cst8xxT_enter_boot();
if(ret == FALSE){
HYN_ERROR("cst8xxT_enter_boot failed");
return FALSE;
}
hyn_8xxTdata->fw_updata_addr = (u8*)fw_bin;
hyn_8xxTdata->fw_updata_len = CST8xxT_BIN_SIZE;
hyn_8xxTdata->hw_info.ic_fw_checksum = cst8xxT_read_checksum();
if(hyn_8xxTdata->need_updata_fw ==0){
hyn_wr_reg(hyn_8xxTdata,0xA006EE,3,buf,0); //exit boot
cst8xxT_rst();
mdelay(50);
hyn_set_i2c_addr(hyn_8xxTdata,MAIN_I2C_ADDR);
cst8xxT_updata_tpinfo();
cst8xxT_set_workmode(NOMAL_MODE,0);
hyn_8xxTdata->need_updata_fw = cst8xxT_updata_judge((u8*)fw_bin,CST8xxT_BIN_SIZE);
}
if(hyn_8xxTdata->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
return TRUE;
}
static int cst8xxT_enter_boot(void)
{
uint8_t t;
hyn_set_i2c_addr(hyn_8xxTdata,BOOT_I2C_ADDR);
for (t = 5;; t += 2)
{
int ok = FALSE;
uint8_t i2c_buf[4] = {0};
if (t >= 15){
return FALSE;
}
cst8xxT_rst();
mdelay(t);
ok = hyn_wr_reg(hyn_8xxTdata, 0xA001AB, 3, i2c_buf, 0);
if(ok == FALSE){
continue;
}
ok = hyn_wr_reg(hyn_8xxTdata, 0xA003, 2, i2c_buf, 1);
if(ok == FALSE){
continue;
}
if (i2c_buf[0] != 0xC1){
continue;
}
break;
}
return TRUE;
}
static int write_code(u8 *bin_addr,uint8_t retry)
{
uint16_t i,t;//,j;
int ok = FALSE;
u8 i2c_buf[512+2];
bin_addr+=6;
for ( i = 0;i < CST8xxT_BIN_SIZE; i += 512)
{
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x14;
i2c_buf[2] = i;
i2c_buf[3] = i >> 8;
ok = hyn_write_data(hyn_8xxTdata, i2c_buf,RW_REG_LEN, 4);
if (ok == FALSE){
break;
}
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x18;
if(0 == hyn_8xxTdata->fw_file_name[0]){
memcpy(i2c_buf + 2, bin_addr + i, 512);
}
else{
ok = hyn_copy_for_updata(hyn_8xxTdata,i2c_buf + 2,i+6,512);
if(ok)break;
}
ok = hyn_write_data(hyn_8xxTdata, i2c_buf,RW_REG_LEN, 514);
if (ok == FALSE){
break;
}
ok = hyn_wr_reg(hyn_8xxTdata, 0xA004EE, 3,i2c_buf,0);
if (ok == FALSE){
break;
}
mdelay(100 * retry);
for (t = 0;; t ++)
{
if (t >= 50){
return FALSE;
}
mdelay(5);
ok = hyn_wr_reg(hyn_8xxTdata,0xA005,2,i2c_buf,1);
if (ok == FALSE){
continue;
}
if (i2c_buf[0] != 0x55){
continue;
}
break;
}
}
return ok;
}
static uint32_t cst8xxT_read_checksum(void)
{
int ok = FALSE,t;
uint8_t i2c_buf[4] = {0};
uint32_t value = 0;
int chip_checksum_ok = FALSE;
// firmware checksum
ok = hyn_wr_reg(hyn_8xxTdata, 0xA00300, 3, i2c_buf, 0);
if (ok == FALSE){
return value;
}
mdelay(100);
for (t = 0;; t += 10)
{
if (t >= 1000){
//return FALSE;
break;
}
mdelay(10);
ok = hyn_wr_reg(hyn_8xxTdata, 0xA000, 2, i2c_buf, 1);
if (ok == FALSE){
continue;
}
if (i2c_buf[0] == 1){
chip_checksum_ok = TRUE;
break;
}
else if (i2c_buf[0] == 2){
chip_checksum_ok = FALSE;
continue;
}
}
if(chip_checksum_ok == FALSE){
hyn_8xxTdata->need_updata_fw = 1;
}
else{
ok = hyn_wr_reg(hyn_8xxTdata, 0xA008, 2, i2c_buf, 2);
if (ok == FALSE){
//return FALSE;
return value;
}
value = i2c_buf[0];
value |= (uint16_t)(i2c_buf[1]) << 8;
}
return value;
}
static int cst8xxT_updata_fw(u8 *bin_addr, u16 len)
{
int retry = 0;
int ok_copy = TRUE;
int ok = FALSE;
u8 i2c_buf[4];
u32 fw_checksum = 0;
// len = len;
HYN_ENTER();
if(0 == hyn_8xxTdata->fw_file_name[0]){
fw_checksum =U8TO16(bin_addr[5],bin_addr[4]);
}
else{
ok = hyn_copy_for_updata(hyn_8xxTdata,i2c_buf,4,2);
if(ok) goto UPDATA_END;
fw_checksum = U8TO16(i2c_buf[1],i2c_buf[0]);
}
hyn_irq_set(hyn_8xxTdata,DISABLE);
for(retry = 1; retry<10; retry++){
ok = cst8xxT_enter_boot();
if (ok == FALSE){
continue;
}
ok = write_code(bin_addr,retry);
if (ok == FALSE){
continue;
}
hyn_8xxTdata->hw_info.ic_fw_checksum = cst8xxT_read_checksum();
if(fw_checksum != hyn_8xxTdata->hw_info.ic_fw_checksum){
continue;
}
if(retry>=5){
ok_copy = FALSE;
break;
}
break;
}
UPDATA_END:
hyn_wr_reg(hyn_8xxTdata,0xA006EE,3,i2c_buf,0); //exit boot
mdelay(2);
cst8xxT_rst();
mdelay(50);
hyn_set_i2c_addr(hyn_8xxTdata,MAIN_I2C_ADDR);
if(ok_copy == TRUE){
cst8xxT_updata_tpinfo();
HYN_INFO("updata_fw success");
}
else{
HYN_ERROR("updata_fw failed");
}
hyn_irq_set(hyn_8xxTdata,ENABLE);
return ok_copy;
}
static int cst8xxT_updata_tpinfo(void)
{
u8 buf[8];
struct tp_info *ic = &hyn_8xxTdata->hw_info;
int ret = 0;
ret = hyn_wr_reg(hyn_8xxTdata,0xA7,1,buf,4);
if(ret == FALSE){
HYN_ERROR("cst8xxT_updata_tpinfo failed");
return FALSE;
}
ic->fw_sensor_txnum = 2;
ic->fw_sensor_rxnum = CUSTOM_SENSOR_NUM;
ic->fw_key_num = hyn_8xxTdata->plat_data.key_num;
ic->fw_res_y = hyn_8xxTdata->plat_data.y_resolution;
ic->fw_res_x = hyn_8xxTdata->plat_data.x_resolution;
ic->fw_project_id = buf[1];
ic->fw_chip_type = buf[0];
ic->fw_ver = buf[2];
HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
return TRUE;
}
static int cst8xxT_updata_judge(u8 *p_fw, u16 len)
{
u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
u8 *p_data = p_fw ;
struct tp_info *ic = &hyn_8xxTdata->hw_info;
f_checksum = U8TO16(p_data[5],p_data[4]);
p_data = p_fw + 6 + CST8xxT_BIN_SIZE - 1 - 15 ;
f_ictype = p_data[0];
f_fw_project_id = (p_data[1]<<24) + (p_data[2]<<16) + (p_data[3]<<8) + (p_data[4]<<0);
f_fw_ver = p_data[5];
HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
if(f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver){
return 1; //need updata
}
return 0;
}
//------------------------------------------------------------------------------//
static int cst8xxT_set_workmode(enum work_mode mode,u8 enable)
{
int ret = 0;
if(hyn_wr_reg(hyn_8xxTdata,0x00,1,NULL,0)){ //check_lp mode
cst8xxT_rst();
mdelay(80);
}
switch(mode){
case NOMAL_MODE:
hyn_esdcheck_switch(hyn_8xxTdata,ENABLE);
hyn_irq_set(hyn_8xxTdata,ENABLE);
break;
case GESTURE_MODE:
hyn_esdcheck_switch(hyn_8xxTdata,DISABLE);
ret = hyn_wr_reg(hyn_8xxTdata,0xE501,2,NULL,0);
break;
case LP_MODE:
break;
case DIFF_MODE:
case RAWDATA_MODE:
hyn_esdcheck_switch(hyn_8xxTdata,DISABLE);
ret = hyn_wr_reg(hyn_8xxTdata,0xFEF8,2,NULL,0);
break;
case FAC_TEST_MODE:
hyn_esdcheck_switch(hyn_8xxTdata,DISABLE);
//hyn_wr_reg(hyn_8xxTdata,0xD119,2,NULL,0);
break;
case DEEPSLEEP:
hyn_esdcheck_switch(hyn_8xxTdata,DISABLE);
hyn_irq_set(hyn_8xxTdata,DISABLE);
ret = hyn_wr_reg(hyn_8xxTdata,0xE503,2,NULL,0);
break;
case CHARGE_EXIT:
case CHARGE_ENTER:
hyn_8xxTdata->charge_is_enable = mode&0x01;
ret = hyn_wr_reg(hyn_8xxTdata,(mode&0x01)? 0xE601:0xE600,2,0,0); //charg mode
mode = hyn_8xxTdata->work_mode; //not switch work mode
HYN_INFO("set_charge:%d",hyn_8xxTdata->charge_is_enable);
break;
default :
ret = -2;
hyn_esdcheck_switch(hyn_8xxTdata,enable);
hyn_8xxTdata->work_mode = NOMAL_MODE;
break;
}
if(ret != -2){
hyn_8xxTdata->work_mode = mode;
}
return ret;
}
static void cst8xxT_rst(void)
{
gpiod_direction_output(hyn_8xxTdata->plat_data.reset_gpio,0);
msleep(11);
gpiod_direction_output(hyn_8xxTdata->plat_data.reset_gpio,1);
}
static int cst8xxT_supend(void)
{
HYN_ENTER();
cst8xxT_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst8xxT_resum(void)
{
cst8xxT_rst();
msleep(50);
cst8xxT_set_workmode(NOMAL_MODE,0);
return 0;
}
static int cst8xxT_report(void)
{
uint8_t i = 0;
uint8_t i2c_buf[3+6*MAX_POINTS_REPORT] = {0};
uint16_t x,y;
uint8_t id = 0,index = 0;
struct hyn_plat_data *dt = &hyn_8xxTdata->plat_data;
memset(&hyn_8xxTdata->rp_buf,0,sizeof(hyn_8xxTdata->rp_buf));
hyn_8xxTdata->rp_buf.report_need = REPORT_NONE;
if(hyn_8xxTdata->work_mode == GESTURE_MODE){
if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,2)){
if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,2))
goto FAILD_END;
}
hyn_8xxTdata->gesture_id = IDX_NULL;
if(i2c_buf[1] == 0x05){ //click
hyn_8xxTdata->gesture_id = IDX_POWER;
hyn_8xxTdata->rp_buf.report_need = REPORT_GES;
}
}
else{
if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,(3+6*2))){
if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,3+6*2))
goto FAILD_END;
}
hyn_8xxTdata->rp_buf.rep_num = i2c_buf[2];
// HYN_INFO("rep_num = %d",hyn_8xxTdata->rp_buf.rep_num);
for(i = 0 ; i < 2 ; i++)
{
id = (i2c_buf[5 + i*6] & 0xf0)>>4;
if(id > 1) continue;
x = (i2c_buf[3 + i*6] & 0x0f);
x = (x<<8) + i2c_buf[4 + i*6];
y = (i2c_buf[5 + i*6] & 0x0f);
y = (y<<8) + i2c_buf[6 + i*6];
hyn_8xxTdata->rp_buf.pos_info[index].pos_id = id;
hyn_8xxTdata->rp_buf.pos_info[index].event = (i2c_buf[3 + i*6] & 0x40) ? 0:1;
hyn_8xxTdata->rp_buf.pos_info[index].pos_x = x ;
hyn_8xxTdata->rp_buf.pos_info[index].pos_y = y ;
// hyn_8xxTdata->rp_buf.pos_info[index].pres_z = (i2c_buf[7 + i*6] <<8) + i2c_buf[8 + i*6] ;
hyn_8xxTdata->rp_buf.pos_info[index].pres_z = 3+(x&0x03); //press mast chang
index++;
}
if(index != 0 || hyn_8xxTdata->rp_buf.rep_num==0) hyn_8xxTdata->rp_buf.report_need = REPORT_POS;
if(dt->key_num){
i = dt->key_num;
while(i){
i--;
if(dt->key_y_coords ==hyn_8xxTdata->rp_buf.pos_info[0].pos_y && dt->key_x_coords[i] == hyn_8xxTdata->rp_buf.pos_info[0].pos_x){
hyn_8xxTdata->rp_buf.key_id = i;
hyn_8xxTdata->rp_buf.key_state = hyn_8xxTdata->rp_buf.pos_info[0].event;
hyn_8xxTdata->rp_buf.report_need = REPORT_KEY;
}
}
}
}
return TRUE;
FAILD_END:
HYN_ERROR("read report data failed");
return FALSE;
}
static u32 cst8xxT_check_esd(void)
{
return TRUE;
}
static int cst8xxT_prox_handle(u8 cmd)
{
return TRUE;
}
static int cst8xxT_get_dbg_data(u8 *buf, u16 len)
{
int ret = -1,read_len = len;
switch (hyn_8xxTdata->work_mode){
case DIFF_MODE:
ret = hyn_wr_reg(hyn_8xxTdata, 0x41, 1,buf,read_len);
break;
case RAWDATA_MODE:
ret = hyn_wr_reg(hyn_8xxTdata, 0x61, 1,buf,read_len);
break;
default:
HYN_ERROR("work_mode:%d",hyn_8xxTdata->work_mode);
break;
}
return ret==0 ? read_len:-1;
}
static int cst8xxT_get_test_result(u8 *buf, u16 len)
{
return 0;
}
const struct hyn_ts_fuc hyn_cst8xxT_fuc = {
.tp_rest = cst8xxT_rst,
.tp_report = cst8xxT_report,
.tp_supend = cst8xxT_supend,
.tp_resum = cst8xxT_resum,
.tp_chip_init = cst8xxT_init,
.tp_updata_fw = cst8xxT_updata_fw,
.tp_set_workmode = cst8xxT_set_workmode,
.tp_check_esd = cst8xxT_check_esd,
.tp_prox_handle = cst8xxT_prox_handle,
.tp_get_dbg_data = cst8xxT_get_dbg_data,
.tp_get_test_result = cst8xxT_get_test_result
};

View File

@@ -0,0 +1,994 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst92xx.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include "cst92xx_fw.h"
#define BOOT_I2C_ADDR (0x5A)
#define MAIN_I2C_ADDR (0x5A)
#define RW_REG_LEN (2)
#define CST92XX_BIN_SIZE (0x7F80)
#define HYNITRON_PROGRAM_PAGE_SIZE (128)
static struct hyn_ts_data *hyn_92xxdata = NULL;
#if 0
static const struct hyn_chip_series hyn_92xx_fw[] = {
{0xCACA9217,0xffffffff,"cst9217",(u8*)fw_bin},//if PART_NO_EN==0 use default chip
{0xCACA9220,0xffffffff,"cst9220",(u8*)fw_bin},
{0,0,"",NULL}
};
#endif
static int cst92xx_updata_judge(u8 *p_fw, u16 len);
static u32 cst92xx_read_checksum(void);
static int cst92xx_updata_tpinfo(void);
static int cst92xx_enter_boot(void);
static void cst92xx_rst(void);
static int cst92xx_set_workmode(enum work_mode mode,u8 enable);
static int cst92xx_read_chip_id(void);
static int cst92xx_init(struct hyn_ts_data* ts_data)
{
int ret = 0;
HYN_ENTER();
hyn_92xxdata = ts_data;
hyn_set_i2c_addr(hyn_92xxdata,BOOT_I2C_ADDR);
ret = cst92xx_read_chip_id();
if(ret == FALSE){
HYN_INFO("cst92xx_read_chip_id failed");
return FALSE;
}
ret = cst92xx_updata_tpinfo();
if(ret == FALSE){
HYN_INFO("cst92xx_updata_tpinfo failed");
}
hyn_92xxdata->fw_updata_addr = (u8*)fw_bin;
hyn_92xxdata->fw_updata_len = CST92XX_BIN_SIZE;
hyn_92xxdata->need_updata_fw = cst92xx_updata_judge((u8*)fw_bin,CST92XX_BIN_SIZE);
if(hyn_92xxdata->need_updata_fw){
HYN_INFO("need updata FW !!!");
}
cst92xx_rst();
msleep(40);
HYN_INFO("cst92xx_init done !!!");
return TRUE;
}
static int cst92xx_enter_boot(void)
{
int ok = FALSE,t;
uint8_t i2c_buf[4] = {0};
for (t = 10;; t += 2)
{
if (t >= 30){
return FALSE;
}
cst92xx_rst();
mdelay(t);
ok = hyn_wr_reg(hyn_92xxdata, 0xA001AA, 3, i2c_buf, 0);
if(ok == FALSE){
continue;
}
mdelay(1);
ok = hyn_wr_reg(hyn_92xxdata, 0xA002, 2, i2c_buf, 2);
if(ok == FALSE){
continue;
}
if ((i2c_buf[0] == 0x55) && (i2c_buf[1] == 0xB0)) {
break;
}
}
ok = hyn_wr_reg(hyn_92xxdata, 0xA00100, 3, i2c_buf, 0);
if(ok == FALSE){
return FALSE;
}
return TRUE;
}
static int erase_all_mem(void)
{
int ok = FALSE,t;
u8 i2c_buf[8];
//erase_all_mem
ok = hyn_wr_reg(hyn_92xxdata, 0xA0140000, 4, i2c_buf, 0);
if (ok == FALSE){
return FALSE;
}
ok = hyn_wr_reg(hyn_92xxdata, 0xA00C807F, 4, i2c_buf, 0);
if (ok == FALSE){
return FALSE;
}
ok = hyn_wr_reg(hyn_92xxdata, 0xA004EC, 3, i2c_buf, 0);
if (ok == FALSE){
return FALSE;
}
mdelay(300);
for (t = 0;; t += 10) {
if (t >= 1000) {
return FALSE;
}
mdelay(10);
ok = hyn_wr_reg(hyn_92xxdata, 0xA005, 2, i2c_buf, 1);
if (ok == FALSE) {
continue;
}
if (i2c_buf[0] == 0x88) {
break;
}
}
return TRUE;
}
static int write_mem_page(uint16_t addr, uint8_t *buf, uint16_t len)
{
int ok = TRUE, t;
uint8_t *i2c_buf;
i2c_buf = kmalloc(1024 + 2, GFP_KERNEL);
memset(i2c_buf, 0, 1024 + 2);
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x0C;
i2c_buf[2] = len;
i2c_buf[3] = len >> 8;
//ok = hyn_i2c_write_r16(HYN_BOOT_I2C_ADDR, 0xA00C, i2c_buf, 2);
ok = hyn_write_data(hyn_92xxdata, i2c_buf,RW_REG_LEN, 4);
if(ok == FALSE){
goto out;
}
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x14;
i2c_buf[2] = addr;
i2c_buf[3] = addr >> 8;
ok = hyn_write_data(hyn_92xxdata, i2c_buf,RW_REG_LEN, 4);
if(ok == FALSE) {
goto out;
}
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x18;
memcpy(i2c_buf + 2, buf, len);
ok = hyn_write_data(hyn_92xxdata, i2c_buf,RW_REG_LEN, len+2);
if(ok == FALSE){
goto out;
}
ok = hyn_wr_reg(hyn_92xxdata,0xA004EE,3,i2c_buf,0);
if(ok == FALSE){
goto out;
}
for (t = 0;; t += 10) {
if (t >= 1000) {
goto out;
}
mdelay(5);
ok = hyn_wr_reg(hyn_92xxdata,0xA005,2,i2c_buf,1);
if(ok == FALSE){
continue;
}
if (i2c_buf[0] == 0x55) {
break;
}
}
out:
kfree(i2c_buf);
return ok;
}
static int write_code(u8 *bin_addr,uint8_t retry)
{
uint8_t data[HYNITRON_PROGRAM_PAGE_SIZE+4];//= (uint8_t *)bin_addr;
uint16_t addr = 0;
uint16_t remain_len = CST92XX_BIN_SIZE;
int ret;
while (remain_len > 0) {
uint16_t cur_len = remain_len;
if (cur_len > HYNITRON_PROGRAM_PAGE_SIZE) {
cur_len = HYNITRON_PROGRAM_PAGE_SIZE;
}
if(0 == hyn_92xxdata->fw_file_name[0]){
memcpy(data, bin_addr + addr, HYNITRON_PROGRAM_PAGE_SIZE);
}else{
ret = hyn_copy_for_updata(hyn_92xxdata,data,addr,HYNITRON_PROGRAM_PAGE_SIZE);
if(ret == FALSE){
HYN_ERROR("hyn_copy_for_updata error");
return FALSE;
}
}
//HYN_INFO("write_code addr 0x%x 0x%x",addr,*data);
if (write_mem_page(addr, data, cur_len) == FALSE) {
return FALSE;
}
//data += cur_len;
addr += cur_len;
remain_len -= cur_len;
}
return TRUE;
}
static uint32_t cst92xx_read_checksum(void)
{
int ok = FALSE;
uint8_t i2c_buf[4] = {0};
uint32_t chip_checksum = 0;
uint8_t retry = 5;
hyn_92xxdata->boot_is_pass = 0;
ok = hyn_wr_reg(hyn_92xxdata,0xA00300,3,i2c_buf,0);
if (ok == FALSE) {
return FALSE;
}
mdelay(2);
while(retry--){
mdelay(5);
ok = hyn_wr_reg(hyn_92xxdata,0xA000,2,i2c_buf,1);
if (ok == FALSE) {
continue;
}
if(i2c_buf[0]!=0) break;
}
mdelay(1);
if(i2c_buf[0] == 0x01){
hyn_92xxdata->boot_is_pass = 1;
memset(i2c_buf,0,sizeof(i2c_buf));
ok = hyn_wr_reg(hyn_92xxdata,0xA008,2,i2c_buf,4);
if (ok == FALSE) {
return FALSE;
}
chip_checksum = ((uint32_t)(i2c_buf[0])) |
(((uint32_t)(i2c_buf[1])) << 8) |
(((uint32_t)(i2c_buf[2])) << 16) |
(((uint32_t)(i2c_buf[3])) << 24);
}
else{
hyn_92xxdata->need_updata_fw = 1;
}
return chip_checksum;
}
static int cst92xx_updata_fw(u8 *bin_addr, u16 len)
{
#define CHECKSUM_OFFECT (0x7F6C)
int retry = 0;
int ok_copy = TRUE;
int ok = FALSE;
u8 i2c_buf[4];
u32 fw_checksum=0;
HYN_ENTER();
if(len < CST92XX_BIN_SIZE){
HYN_ERROR("len = %d",len);
goto UPDATA_END;
}
// if(len > CST92XX_BIN_SIZE) len = CST92XX_BIN_SIZE;
if(0 != hyn_92xxdata->fw_file_name[0]){
//node to update
ok = hyn_copy_for_updata(hyn_92xxdata,i2c_buf,CST92XX_BIN_SIZE-20,4);
fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]);
if(hyn_92xxdata->hw_info.ic_fw_checksum == fw_checksum || ok != 0){
HYN_INFO("no update,fw_checksum is same:0x%04x",fw_checksum);
goto UPDATA_END;
}
}else{
fw_checksum = U8TO32(bin_addr[CHECKSUM_OFFECT+3],bin_addr[CHECKSUM_OFFECT+2],bin_addr[CHECKSUM_OFFECT+1],bin_addr[CHECKSUM_OFFECT+0]);
}
HYN_INFO("updating fw checksum:0x%04x",fw_checksum);
hyn_irq_set(hyn_92xxdata,DISABLE);
hyn_esdcheck_switch(hyn_92xxdata,DISABLE);
hyn_set_i2c_addr(hyn_92xxdata,BOOT_I2C_ADDR);
HYN_INFO("updata_fw start");
for(retry = 1; retry<5; retry++){
hyn_92xxdata->fw_updata_process = 0;
ok = cst92xx_enter_boot();
if (ok == FALSE){
continue;
}
hyn_92xxdata->fw_updata_process = 10;
ok = erase_all_mem();
if (ok == FALSE){
continue;
}
hyn_92xxdata->fw_updata_process = 20;
ok = write_code(bin_addr,retry);
if (ok == FALSE){
continue;
}
hyn_92xxdata->fw_updata_process = 30;
hyn_92xxdata->hw_info.ic_fw_checksum = cst92xx_read_checksum();
if(fw_checksum != hyn_92xxdata->hw_info.ic_fw_checksum){
HYN_INFO("out data fw checksum err:0x%04x",hyn_92xxdata->hw_info.ic_fw_checksum);
hyn_92xxdata->fw_updata_process |= 0x80;
continue;
}
hyn_92xxdata->fw_updata_process = 100;
if(retry>=5){
ok_copy = FALSE;
break;
}
break;
}
hyn_wr_reg(hyn_92xxdata,0xA006EE,3,i2c_buf,0); //exit boot
mdelay(2);
UPDATA_END:
cst92xx_rst();
mdelay(50);
hyn_set_i2c_addr(hyn_92xxdata,MAIN_I2C_ADDR);
if(ok_copy == TRUE){
cst92xx_updata_tpinfo();
HYN_INFO("updata_fw success");
}
else{
HYN_INFO("updata_fw failed");
}
hyn_irq_set(hyn_92xxdata,ENABLE);
return ok_copy;
}
static int16_t read_word_from_mem(uint8_t type, uint16_t addr, uint32_t *value)
{
int16_t ret = 0;
uint8_t i2c_buf[4] = {0},t;
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x10;
i2c_buf[2] = type;
ret = hyn_write_data(hyn_92xxdata,i2c_buf,2,3);
if (ret)
{
return -1;
}
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x0C;
i2c_buf[2] = addr;
i2c_buf[3] = addr >> 8;
ret = hyn_write_data(hyn_92xxdata,i2c_buf,2,4);
if (ret)
{
return -1;
}
i2c_buf[0] = 0xA0;
i2c_buf[1] = 0x04;
i2c_buf[2] = 0xE4;
ret = hyn_write_data(hyn_92xxdata,i2c_buf,2,3);
if (ret)
{
return -1;
}
for (t = 0;; t++)
{
if (t >= 100)
{
return -1;
}
ret =hyn_wr_reg(hyn_92xxdata,0xA004,2,i2c_buf,1);
if (ret)
{
continue;
}
if (i2c_buf[0] == 0x00)
{
break;
}
}
ret =hyn_wr_reg(hyn_92xxdata,0xA018,2,i2c_buf,4);
if (ret)
{
return -1;
}
*value = ((uint32_t)(i2c_buf[0])) |
(((uint32_t)(i2c_buf[1])) << 8) |
(((uint32_t)(i2c_buf[2])) << 16) |
(((uint32_t)(i2c_buf[3])) << 24);
return 0;
}
static int cst92xx_read_chip_id(void)
{
int16_t ret = 0;
uint8_t retry = 3;
uint32_t partno_chip_type = 0, module_id = 0;
ret = cst92xx_enter_boot();
if (ret == FALSE)
{
HYN_ERROR("enter_bootloader error");
return -1;
}
for (; retry > 0; retry--)
{
// partno
ret = read_word_from_mem(1, 0x077C, &partno_chip_type);
if (ret)
{
continue;
}
// module id
ret = read_word_from_mem(0, 0x7FC0, &module_id);
if (ret)
{
continue;
}
if ((partno_chip_type >> 16) == 0xCACA)
{
partno_chip_type &= 0xffff;
break;
}
}
cst92xx_rst();
msleep(30);
HYN_INFO("partno_chip_type: 0x%04x", partno_chip_type);
HYN_INFO("module_id: 0x%04x", module_id);
if ((partno_chip_type != 0x9217) && (partno_chip_type != 0x9220))
{
HYN_ERROR("partno_chip_type error 0x%04x", partno_chip_type);
//return -1;
}
return 0;
}
static int cst92xx_updata_tpinfo(void)
{
u8 buf[30];
struct tp_info *ic = &hyn_92xxdata->hw_info;
int ret = 0;
cst92xx_set_workmode(0xff,DISABLE);
ret = hyn_wr_reg(hyn_92xxdata,0xD101,2,buf,0);
if(ret == FALSE){
return FALSE;
}
mdelay(5);
//firmware_project_id firmware_ic_type
ret = hyn_wr_reg(hyn_92xxdata,0xD1F4,2,buf,28);
if(ret == FALSE){
return FALSE;
}
ic->fw_project_id = ((uint16_t)buf[17] <<8) + buf[16];
ic->fw_chip_type = ((uint16_t)buf[19] <<8) + buf[18];
//firmware_version
ic->fw_ver = (buf[23]<<24)|(buf[22]<<16)|(buf[21]<<8)|buf[20];
//tx_num rx_num key_num
ic->fw_sensor_txnum = ((uint16_t)buf[1]<<8) + buf[0];
ic->fw_sensor_rxnum = buf[2];
ic->fw_key_num = buf[3];
ic->fw_res_y = (buf[7]<<8)|buf[6];
ic->fw_res_x = (buf[5]<<8)|buf[4];
//fw_checksum
ic->ic_fw_checksum = (buf[27]<<24)|(buf[26]<<16)|(buf[25]<<8)|buf[24];
HYN_INFO("IC_info project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum);
cst92xx_set_workmode(NOMAL_MODE,ENABLE);
return TRUE;
}
static int cst92xx_updata_judge(u8 *p_fw, u16 len)
{
u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id;
u8 *p_data = p_fw + len - 28; //7F64
struct tp_info *ic = &hyn_92xxdata->hw_info;
int ret;
ret = cst92xx_enter_boot();
if (ret == FALSE){
HYN_INFO("cst92xx_enter_boot fail,need update");
return 1;
}
hyn_92xxdata->hw_info.ic_fw_checksum = cst92xx_read_checksum();
if(hyn_92xxdata->boot_is_pass == 0){
HYN_INFO("boot_is_pass %d,need force update",hyn_92xxdata->boot_is_pass);
return 1; //need updata
}
f_fw_project_id = U8TO16(p_data[1],p_data[0]);
f_ictype = U8TO16(p_data[3],p_data[2]);
f_fw_ver = U8TO16(p_data[7],p_data[6]);
f_fw_ver = (f_fw_ver<<16)|U8TO16(p_data[5],p_data[4]);
f_checksum = U8TO16(p_data[11],p_data[10]);
f_checksum = (f_checksum << 16)|U8TO16(p_data[9],p_data[8]);
HYN_INFO("Bin_info project_id:0x%04x ictype:0x%04x fw_ver:0x%x checksum:0x%x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum);
if(f_ictype != ic->fw_chip_type || f_fw_project_id != ic->fw_project_id){
HYN_ERROR("not update,please confirm: ic_type 0x%04x,ic_project_id 0x%04x",ic->fw_chip_type,ic->fw_project_id);
return 0; //not updata
}
if(f_checksum != ic->ic_fw_checksum && f_fw_ver > ic->fw_ver){
HYN_INFO("need update!");
return 1; //need updata
}
HYN_INFO("cst92xx_updata_judge done, no need update");
return 0;
}
//------------------------------------------------------------------------------//
static int cst92xx_set_workmode(enum work_mode mode,u8 enable)
{
int ok = FALSE;
uint8_t i2c_buf[4] = {0};
uint8_t i = 0;
hyn_92xxdata->work_mode = mode;
for(i=0;i<3;i++)
{
ok = hyn_wr_reg(hyn_92xxdata,0xD11E,2,i2c_buf,0);
if (ok == FALSE) {
msleep(1);
continue;
}
msleep(1);
ok = hyn_wr_reg(hyn_92xxdata,0x0002,2,i2c_buf,2);
if (ok == FALSE) {
msleep(1);
continue;
}
if(i2c_buf[1] == 0x1E){
break;
}
}
switch(mode){
case NOMAL_MODE:
hyn_irq_set(hyn_92xxdata,ENABLE);
hyn_esdcheck_switch(hyn_92xxdata,ENABLE);
ok = hyn_wr_reg(hyn_92xxdata,0xD109,2,i2c_buf,0);
break;
case GESTURE_MODE:
hyn_esdcheck_switch(hyn_92xxdata,ENABLE);
ok = hyn_wr_reg(hyn_92xxdata,0xD104,2,i2c_buf,0);
break;
case LP_MODE:
hyn_esdcheck_switch(hyn_92xxdata,DISABLE);
ok = hyn_wr_reg(hyn_92xxdata,0xD107,2,i2c_buf,0);
break;
case DIFF_MODE:
hyn_esdcheck_switch(hyn_92xxdata,DISABLE);
ok = hyn_wr_reg(hyn_92xxdata,0xD10D,2,i2c_buf,0);
break;
case RAWDATA_MODE:
hyn_esdcheck_switch(hyn_92xxdata,DISABLE);
ok = hyn_wr_reg(hyn_92xxdata,0xD10A,2,i2c_buf,0);
break;
case FAC_TEST_MODE:
hyn_esdcheck_switch(hyn_92xxdata,DISABLE);
hyn_wr_reg(hyn_92xxdata,0xD114,2,i2c_buf,0);
msleep(50);
break;
case DEEPSLEEP:
hyn_esdcheck_switch(hyn_92xxdata,DISABLE);
hyn_wr_reg(hyn_92xxdata,0xD105,2,i2c_buf,0);
break;
default :
hyn_92xxdata->work_mode = NOMAL_MODE;
hyn_esdcheck_switch(hyn_92xxdata,enable);
ok = -2;
break;
}
if(ok != -2){
hyn_92xxdata->work_mode = mode;
}
HYN_INFO("set_workmode:%d ret:%d",mode,ok);
return ok;
}
static void cst92xx_rst(void)
{
gpiod_direction_output(hyn_92xxdata->plat_data.reset_gpio,0);
msleep(8);
gpiod_direction_output(hyn_92xxdata->plat_data.reset_gpio,1);
}
static int cst92xx_supend(void)
{
HYN_ENTER();
cst92xx_set_workmode(DEEPSLEEP,0);
return 0;
}
static int cst92xx_resum(void)
{
cst92xx_rst();
msleep(50);
cst92xx_set_workmode(NOMAL_MODE,1);
return 0;
}
static int cst92xx_report(void)
{
int ok = FALSE;
uint8_t i2c_buf[MAX_POINTS_REPORT*5+5] = {0};
uint8_t finger_num = 0;
uint8_t key_state=0,key_id = 0;
hyn_92xxdata->rp_buf.report_need = REPORT_NONE;
ok = hyn_wr_reg(hyn_92xxdata,0xD000,2,i2c_buf,sizeof(i2c_buf));
if (ok == FALSE){
return FALSE;
}
ok = hyn_wr_reg(hyn_92xxdata,0xD000AB,3,i2c_buf,0);
if (ok == FALSE){
return FALSE;
}
if (i2c_buf[6] != 0xAB) {
HYN_INFO("fail buf[6]=0x%02x",i2c_buf[6]);
return FALSE;
}
finger_num = i2c_buf[5] & 0x7F;
if (finger_num > MAX_POINTS_REPORT) {
HYN_INFO("fail finger_num=%d",finger_num);
return TRUE;
}
hyn_92xxdata->rp_buf.rep_num = finger_num;
if ((i2c_buf[5] & 0x80) == 0x80) { // button
uint8_t *data = i2c_buf + finger_num * 5;
if (finger_num > 0) {
data += 2;
}
key_state = data[0];//0x83:按键有触<E69C89>? 0x80:按键<E68C89>?<3F>?
key_id = data[1]; // data[1]; :0x17 0x27 0x37
if(key_state&0x80){
hyn_92xxdata->rp_buf.report_need |= REPORT_KEY;
if((key_id == hyn_92xxdata->rp_buf.key_id || 0 == hyn_92xxdata->rp_buf.key_state)&& key_state == 0x83){
hyn_92xxdata->rp_buf.key_id = key_id;
hyn_92xxdata->rp_buf.key_state = 1;
}
else{
hyn_92xxdata->rp_buf.key_state = 0;
}
}
}
else//pos
{
uint8_t index = 0,i;
if((i2c_buf[4]&0xF0) > 0){
if((i2c_buf[4]&0x80) == 0x80)
hyn_92xxdata->gesture_id = 14;//KEY_POWER;// palm
else if(i2c_buf[4]&0x70)
hyn_92xxdata->gesture_id = 14;//GESTURE wakeup
HYN_INFO("i2c_buf[4]=0x%x,gesture_id=0x%x",i2c_buf[4],hyn_92xxdata->gesture_id);
hyn_92xxdata->rp_buf.report_need |= REPORT_GES;
return TRUE;
}
hyn_92xxdata->rp_buf.report_need |= REPORT_POS;
if (finger_num > 0) {
uint8_t *data = i2c_buf;
//uint8_t *data_ges = i2c_buf + finger_num * 5 + 2;
uint8_t id = data[0] >> 4;
uint8_t switch_ = data[0] & 0x0F;
uint16_t x = ((uint16_t)(data[1]) << 4) | (data[3] >> 4);
uint16_t y = ((uint16_t)(data[2]) << 4) | (data[3] & 0x0F);
uint16_t z = (data[3] & 0x1F) + 0x03;
HYN_INFO("finger=%d id=%d x=%d y=%d z=%d",finger_num,id,x,y,z);
if (id < MAX_POINTS_REPORT) {
hyn_92xxdata->rp_buf.pos_info[index].pos_id = id;
hyn_92xxdata->rp_buf.pos_info[index].event = (switch_ == 0x06 || switch_ == 0x07) ? 1 : 0;
hyn_92xxdata->rp_buf.pos_info[index].pos_x = x;
hyn_92xxdata->rp_buf.pos_info[index].pos_y = y;
hyn_92xxdata->rp_buf.pos_info[index].pres_z = z;
index++;
}
}
for (i = 1; i < finger_num; i++) {
uint8_t *data = i2c_buf+5*i+2;
uint8_t id = data[0] >> 4;
uint8_t switch_ = data[0] & 0x0F;
uint16_t x = ((uint16_t)(data[1]) << 4) | (data[3] >> 4);
uint16_t y = ((uint16_t)(data[2]) << 4) | (data[3] & 0x0F);
uint16_t z = (data[4] & 0x7F);
if (id < MAX_POINTS_REPORT) {
hyn_92xxdata->rp_buf.pos_info[index].pos_id = id;
hyn_92xxdata->rp_buf.pos_info[index].event = (switch_ == 0x06) ? 1 : 0;
hyn_92xxdata->rp_buf.pos_info[index].pos_x = x;
hyn_92xxdata->rp_buf.pos_info[index].pos_y = y;
hyn_92xxdata->rp_buf.pos_info[index].pres_z = z;
index++;
}
}
}
return TRUE;
}
#if 0
static u32 cst92xx_check_esd(void)
{
int ret = 0;
uint8_t retry=3;
u8 buf[6];
HYN_ENTER();
while (retry--)
{
ret = hyn_wr_reg(hyn_92xxdata,0xD040,2,buf,0);
ret = hyn_wr_reg(hyn_92xxdata,0xD040,2,buf,6);
if(ret ==0 && hyn_sum16(0xA5,buf,4)==U8TO16(buf[4],buf[5])){
ret = U8TO32(buf[0],buf[1],buf[2],buf[3]);
break;
}
}
return ret;
}
#endif
static u32 cst92xx_check_esd(void)
{
int16_t ok = FALSE;
uint8_t i2c_buf[6], retry;
uint8_t flag = 0;
uint32_t esd_value = 0;
retry = 4;
flag = 0;
while (retry--){
hyn_wr_reg(hyn_92xxdata,0xD048,2,i2c_buf,0);
udelay(200);
ok = hyn_wr_reg(hyn_92xxdata,0xD048,2,i2c_buf,2);
if (ok == FALSE){
msleep(1);
continue;
} else
{
// if (( (i2c_buf[0] & 0xF0) == 0x20 || (i2c_buf[0] & 0xF0) == 0xA0 ) && (i2c_buf[0] & 0x0F) < 10)
if ((i2c_buf[0] == 0x20) || (i2c_buf[0] == 0xA0))
{
flag = 1;
esd_value = i2c_buf[0];
break;
} else {
HYN_INFO("ESD data NA,need retry: 0x%x ", i2c_buf[0]);
msleep(2);
continue;
}
}
}
HYN_INFO("ESD data:%d,0x%04x,0x%04x", flag, esd_value, hyn_92xxdata->esd_last_value);
if (flag == 0){
hyn_power_source_ctrl(hyn_92xxdata, 0);
mdelay(2);
hyn_power_source_ctrl(hyn_92xxdata, 1);
mdelay(2);
cst92xx_rst();
msleep(40);
esd_value = 0;
hyn_92xxdata->esd_last_value = 0;
HYN_INFO("esd_check power reset ic");
}
if ((hyn_92xxdata->work_mode == GESTURE_MODE) && (esd_value != 0xA0))
{
ok = hyn_wr_reg(hyn_92xxdata,0xD104,2,0,0);
if (ok == FALSE){
HYN_ERROR("enter_sleep failed");
}
}
hyn_92xxdata->esd_last_value = esd_value;
return esd_value;
}
static int cst92xx_prox_handle(u8 cmd)
{
return TRUE;
}
static int cst92xx_get_dbg_data(u8 *buf, u16 len)
{
int ret = -1;
u16 read_len = (hyn_92xxdata->hw_info.fw_sensor_txnum * hyn_92xxdata->hw_info.fw_sensor_rxnum)*2;
u16 total_len = read_len + (hyn_92xxdata->hw_info.fw_sensor_txnum + hyn_92xxdata->hw_info.fw_sensor_rxnum)*2;
HYN_ENTER();
if(total_len > len){
HYN_ERROR("buf too small");
return -1;
}
switch(hyn_92xxdata->work_mode){
case DIFF_MODE:
case RAWDATA_MODE:
ret = hyn_wr_reg(hyn_92xxdata,0x1000,2,buf,read_len); //mt
buf += read_len;
read_len = hyn_92xxdata->hw_info.fw_sensor_rxnum*2;
ret |= hyn_wr_reg(hyn_92xxdata,0x7000,2,buf,read_len); //rx
buf += read_len;
read_len = hyn_92xxdata->hw_info.fw_sensor_txnum*2;
ret |= hyn_wr_reg(hyn_92xxdata,0x7200,2,buf,read_len); //tx
ret |= hyn_wr_reg(hyn_92xxdata,0x000500,3,0,0); //end
break;
default:
HYN_ERROR("work_mode:%d",hyn_92xxdata->work_mode);
break;
}
return ret==0 ? total_len:-1;
}
#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini"
#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log"
#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST)
static int cst92xx_get_test_result(u8 *buf, u16 len)
{
int ret = 0,timeout;
struct tp_info *ic = &hyn_92xxdata->hw_info;
u16 scap_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2;
u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2,i = 0;
u16 *raw_s;
HYN_ENTER();
if((mt_len*3 + scap_len) > len || mt_len==0){
HYN_ERROR("buf too small");
return FAC_GET_DATA_FAIL;
}
HYN_INFO("---open_higdrv---");
timeout = 500;
hyn_wr_reg(hyn_92xxdata,0xD110,2,buf,0); ////test open high
while(--timeout){ //wait rise edge
if(hyn_wait_irq_timeout(hyn_92xxdata,100) == 0) break;
msleep(10);
}
if(hyn_wr_reg(hyn_92xxdata,0x3000,2,buf,mt_len)){ //open high
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read open high failed");
goto selftest_end;
}
hyn_wr_reg(hyn_92xxdata,0x000005,3,buf,0);
HYN_INFO("---open_low---");
timeout = 500;
hyn_wr_reg(hyn_92xxdata,0xD111,2,buf,0); ////test open low
while(--timeout){ //wait rise edge
if(hyn_wait_irq_timeout(hyn_92xxdata,100) == 0) break;
msleep(10);
}
if(hyn_wr_reg(hyn_92xxdata,0x1000,2,buf + mt_len,mt_len)){ //open low
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read open low failed");
goto selftest_end;
}
hyn_wr_reg(hyn_92xxdata,0x000005,3,buf,0);
//short test
HYN_INFO("---short---");
timeout = 500;
hyn_wr_reg(hyn_92xxdata,0xD112,2,buf,0); //// short test
while(--timeout){ //wait rise edge
if(hyn_wait_irq_timeout(hyn_92xxdata,100) == 0) break;
msleep(10);
}
if(hyn_wr_reg(hyn_92xxdata,0x5000,2,buf+(mt_len*2),scap_len)){
ret = FAC_GET_DATA_FAIL;
HYN_ERROR("read fac short failed");
goto selftest_end;
}
else{
raw_s = (u16*)(buf + mt_len*2);
HYN_INFO("raw_s start data = %d",*(raw_s));
for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){
HYN_INFO("short raw data = %d %d",i,*(raw_s+i));
if(U16REV((u16)*raw_s) != 0) *raw_s = 2000 / U16REV((u16)*raw_s);
else *raw_s =0;
HYN_INFO("short reprocess data = %d %d",i,*(raw_s+i));
raw_s++;
}
}
//read data finlish start test
ret = hyn_factory_multitest(hyn_92xxdata ,FACTEST_PATH, buf,(s16*)(buf+scap_len+mt_len*2),FACTEST_ITEM);
selftest_end:
if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_92xxdata,(s16*)buf,ret,FACTEST_ITEM)){
HYN_INFO("fac_test log save success");
}
cst92xx_rst();
msleep(40);
return ret;
}
const struct hyn_ts_fuc hyn_cst92xx_fuc = {
.tp_rest = cst92xx_rst,
.tp_report = cst92xx_report,
.tp_supend = cst92xx_supend,
.tp_resum = cst92xx_resum,
.tp_chip_init = cst92xx_init,
.tp_updata_fw = cst92xx_updata_fw,
.tp_set_workmode = cst92xx_set_workmode,
.tp_check_esd = cst92xx_check_esd,
.tp_prox_handle = cst92xx_prox_handle,
.tp_get_dbg_data = cst92xx_get_dbg_data,
.tp_get_test_result = cst92xx_get_test_result
};

View File

@@ -0,0 +1,982 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_core.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "hyn_core.h"
#define HYN_DRIVER_NAME "hyn_ts"
static struct hyn_ts_data *hyn_data = NULL;
static const struct hyn_ts_fuc* hyn_fun = NULL;
static const struct of_device_id hyn_of_match_table[] = {
{.compatible = "hyn,66xx", .data = &hyn_cst66xx_fuc,}, /*support 36xx 35xx 66xx 68xx 148E*/
{.compatible = "hyn,36xxes", .data = &hyn_cst36xxes_fuc,}, /*support 154es 3654es 3640es*/
{.compatible = "hyn,3240", .data = &hyn_cst3240_fuc,}, /*support 3240 */
{.compatible = "hyn,92xx", .data = &hyn_cst92xx_fuc,}, /*support 9217、9220 */
{.compatible = "hyn,3xx", .data = &hyn_cst3xx_fuc,}, /*support 340 348 328 128 140 148*/
{.compatible = "hyn,7xx", .data = &hyn_cst7xx_fuc,}, /*support 726 826 836u*/
{.compatible = "hyn,8xxt", .data = &hyn_cst8xxT_fuc,}, /*support 816t 816d 820 08C*/
{.compatible = "hyn,226se", .data = &hyn_cst226se_fuc,}, /*support 226se 8922*/
{},
};
MODULE_DEVICE_TABLE(of, hyn_of_match_table);
static int hyn_check_ic(struct hyn_ts_data *ts_data)
{
const struct of_device_id *of_dev;
of_dev = of_match_device(hyn_of_match_table,ts_data->dev);
if (!of_dev) {
return -1;
}
hyn_fun = of_dev->data;
if (IS_ERR_OR_NULL(hyn_fun) || IS_ERR_OR_NULL(hyn_fun->tp_chip_init)
|| hyn_fun->tp_chip_init(ts_data)) {
return -2;
}
ts_data->hyn_fuc_used = hyn_fun;
return 0;
}
static int hyn_parse_dt(struct hyn_ts_data *ts_data)
{
int ret = 0;
struct device *dev = ts_data->dev;
struct hyn_plat_data* dt = &ts_data->plat_data;
HYN_ENTER();
if (dev->of_node) {
u32 buf[8];
struct device_node *np = dev->of_node;
//vcc supply
dt->vdd_i2c = NULL;
dt->vdd_ana = NULL;
if (of_property_read_bool(np,"vdd_ana-supply")) {
dt->vdd_ana = regulator_get(dev, "vdd_ana");
if (IS_ERR_OR_NULL(dt->vdd_ana)) {
dt->vdd_ana = NULL;
HYN_ERROR("regulator_get vdd_ana failed");
}
}
else{
HYN_INFO("vdd_ana not config");
}
//iovcc supply
if (of_property_read_bool(np,"vcc_i2c-supply")) {
dt->vdd_i2c = regulator_get(dev, "vcc_i2c");
if (IS_ERR_OR_NULL(dt->vdd_i2c)) {
dt->vdd_i2c = NULL;
HYN_ERROR("regulator_get vdd_i2c failed");
}
}
else{
HYN_INFO("vdd_i2c not config");
}
//gpio info
dt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(dt->reset_gpio)) {
ret = PTR_ERR(dt->reset_gpio);
HYN_ERROR("failed to request reset GPIO: %d\n", ret);
return -EPROBE_DEFER;
}
dt->irq_gpio = devm_gpiod_get(dev, "irq", GPIOD_ASIS);
if (IS_ERR(dt->irq_gpio)) {
ret = PTR_ERR(dt->irq_gpio);
HYN_ERROR("failed to request irq GPIO: %d\n", ret);
return -EPROBE_DEFER;
}
//pin_ctl
ret =-1;
dt->pinctl = devm_pinctrl_get(dev);
if (!IS_ERR_OR_NULL(dt->pinctl)) {
dt->pin_active = pinctrl_lookup_state(dt->pinctl, "ts_active");
dt->pin_suspend= pinctrl_lookup_state(dt->pinctl, "ts_suspend");
if (!IS_ERR_OR_NULL(dt->pin_active) && !IS_ERR_OR_NULL(dt->pin_suspend)) {
ret = 0;
}
}
if (ret) {
HYN_INFO("pinctrl not config or can't find \"ts-active\" \"ts_suspend\"");
dt->pinctl = NULL;
dt->pin_active = NULL;
dt->pin_suspend= NULL;
}
// point info
ret = of_property_read_u32(np, "max-touch-number", &dt->max_touch_num);
ret |= of_property_read_u32(np, "pos-swap", &dt->swap_xy);
ret |= of_property_read_u32(np, "posx-reverse", &dt->reverse_x);
ret |= of_property_read_u32(np, "posy-reverse", &dt->reverse_y);
ret |= of_property_read_u32_array(np, "display-coords", buf, 4);
dt->x_resolution = buf[2];
dt->y_resolution = buf[3];
HYN_INFO("dts x_res = %d,y_res = %d,touch-number = %d swap_xy = %d reversex = %d reversey = %d",
dt->x_resolution,dt->y_resolution,dt->max_touch_num,dt->swap_xy,dt->reverse_x,dt->reverse_y);
if (ret < 0) {
HYN_ERROR("dts get screen failed");
return -EINVAL;
}
// key info
ret = of_property_read_u32(np, "key-number", &dt->key_num);
if (ret>=0 && dt->key_num && dt->key_num<=8) {
ret |= of_property_read_u32(np, "key-y-coord", &dt->key_y_coords);
ret |= of_property_read_u32_array(np, "key-x-coords", dt->key_x_coords, dt->key_num);
ret |= of_property_read_u32_array(np, "keys", dt->key_code, dt->key_num);
if (ret < 0) {
HYN_ERROR("dts get screen failed");
return -EINVAL;
}
}
else{
HYN_INFO("key not config");
dt->key_num = 0;
}
return 0;
}
else{
HYN_ERROR("dts match failed");
return -ENODEV;
}
}
static int hyn_poweron(struct hyn_ts_data *ts_data)
{
int ret = 0;
struct hyn_plat_data* dt = &ts_data->plat_data;
if (!IS_ERR_OR_NULL(hyn_data->plat_data.pinctl)) {
if (pinctrl_select_state(dt->pinctl, dt->pin_active)) {
HYN_ERROR("pin active set failed");
ret = -EPROBE_DEFER;
goto GPIO_SET_FAILE;
}
}
if (!IS_ERR_OR_NULL(dt->vdd_ana)) {
if (regulator_count_voltages(dt->vdd_ana) > 0) {
if (regulator_set_voltage(dt->vdd_ana, 2800000, 3300000)) {
HYN_ERROR("set voltage vdd_ana failed");
}
}
}
if (!IS_ERR_OR_NULL(dt->vdd_i2c)) {
if (regulator_count_voltages(dt->vdd_i2c) > 0) {
if (regulator_set_voltage(dt->vdd_i2c, 1800000, 1800000)) {
HYN_ERROR("set voltage vdd_i2c failed");
}
}
}
if (hyn_power_source_ctrl(hyn_data, 1)) {
HYN_ERROR("enable power failed");
}
mdelay(5);
gpiod_direction_output(dt->reset_gpio, 1);
return 0;
GPIO_SET_FAILE:
return ret;
}
static int hyn_input_dev_init(struct hyn_ts_data *ts_data)
{
int key_num = 0;//,ret =0;
struct hyn_plat_data *dt = &ts_data->plat_data;
struct input_dev *input_dev;
HYN_ENTER();
input_dev = input_allocate_device();
if (!input_dev) {
HYN_ERROR("Failed to allocate memory for input device");
return -ENOMEM;
}
input_dev->name = HYN_DRIVER_NAME;
input_dev->id.bustype = ts_data->bus_type;
input_dev->dev.parent = ts_data->dev;
input_set_drvdata(input_dev, ts_data);
__set_bit(EV_SYN, input_dev->evbit);
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
for (key_num = 0; key_num < dt->key_num; key_num++)
input_set_capability(input_dev, EV_KEY, dt->key_code[key_num]);
#if HYN_MT_PROTOCOL_B_EN
set_bit(BTN_TOOL_FINGER,input_dev->keybit);
//input_mt_init_slots(input_dev, dt->max_touch_num+1);
input_mt_init_slots(input_dev, dt->max_touch_num+1, INPUT_MT_DIRECT);
#else
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
#endif
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, dt->max_touch_num, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, dt->x_resolution,0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, dt->y_resolution,0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
ts_data->input_dev = input_dev;
return 0;
}
static void release_all_finger(struct hyn_ts_data *ts_data)
{
HYN_ENTER();
if (ts_data->report_id_flg) {
#if HYN_MT_PROTOCOL_B_EN
u8 i;
for(i=0; i< ts_data->plat_data.max_touch_num; i++) {
if (ts_data->report_id_flg & (1UL<<i)) {
// HYN_INFO("release %d",i);
input_mt_slot(ts_data->input_dev, i);
input_report_abs(ts_data->input_dev, ABS_MT_TRACKING_ID, -1);
input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, false);
}
}
input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
#else
input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
input_mt_sync(ts_data->input_dev);
#endif
}
ts_data->report_id_flg = 0;
}
static void touch_updata(u8 idx,u8 event)
{
struct ts_frame *rep_frame = &hyn_data->rp_buf;
struct input_dev *dev = hyn_data->input_dev;
u16 zpress = rep_frame->pos_info[idx].pres_z;
if (zpress < 10) {
zpress = zpress+(rep_frame->pos_info[idx].pos_x&0x03) + (rep_frame->pos_info[idx].pos_y&0x03);
}
if (event) {
hyn_data->report_id_flg |= (1UL<< rep_frame->pos_info[idx].pos_id);
}
#if HYN_MT_PROTOCOL_B_EN
if (event) {
input_report_key(dev, BTN_TOUCH, 1);
input_mt_slot(dev, rep_frame->pos_info[idx].pos_id);
input_mt_report_slot_state(dev, MT_TOOL_FINGER, 1);
input_report_abs(dev, ABS_MT_TRACKING_ID, rep_frame->pos_info[idx].pos_id);
input_report_abs(dev, ABS_MT_POSITION_X, rep_frame->pos_info[idx].pos_x);
input_report_abs(dev, ABS_MT_POSITION_Y, rep_frame->pos_info[idx].pos_y);
input_report_abs(dev, ABS_MT_TOUCH_MAJOR, zpress>>3);
input_report_abs(dev, ABS_MT_WIDTH_MAJOR, zpress>>3);
input_report_abs(dev, ABS_MT_PRESSURE, zpress);
}
else{
input_mt_slot(dev, rep_frame->pos_info[idx].pos_id);
input_report_abs(dev, ABS_MT_TRACKING_ID, -1);
input_mt_report_slot_state(dev, MT_TOOL_FINGER, 0);
}
#else
if (event) {
input_report_key(dev, BTN_TOUCH, 1);
input_report_abs(dev, ABS_MT_PRESSURE, zpress);
input_report_abs(dev, ABS_MT_TRACKING_ID, rep_frame->pos_info[idx].pos_id);
input_report_abs(dev, ABS_MT_TOUCH_MAJOR, zpress>>3);
// input_report_abs(dev, ABS_MT_WIDTH_MAJOR, zpress>>3);
input_report_abs(dev, ABS_MT_POSITION_X, rep_frame->pos_info[idx].pos_x);
input_report_abs(dev, ABS_MT_POSITION_Y, rep_frame->pos_info[idx].pos_y);
input_mt_sync(dev);
}
#endif
}
static void hyn_irq_report_work(struct work_struct *work)
{
struct hyn_ts_data *ts_data = hyn_data;
struct ts_frame *rep_frame = &hyn_data->rp_buf;
struct input_dev *dev = hyn_data->input_dev;
struct hyn_plat_data *dt = &hyn_data->plat_data;
u16 xpos,ypos;
int reprot_state_clr = 0;
if (hyn_fun->tp_report()) {
HYN_INFO("Ignore illegal data");
return;
}
mutex_lock(&ts_data->mutex_report);
if (rep_frame->report_need & REPORT_KEY) { //key
#if KEY_USED_POS_REPORT
rep_frame->pos_info[0].pos_id = 0;
rep_frame->pos_info[0].pos_x = dt->key_x_coords[rep_frame->key_id];
rep_frame->pos_info[0].pos_y = dt->key_y_coords;
rep_frame->pos_info[0].pres_z = 100;
touch_updata(0,rep_frame->key_state ? 1:0);
#else
input_report_key(dev,dt->key_code[rep_frame->key_id],rep_frame->key_state ? 1:0);
#endif
if (rep_frame->key_state==0) {
reprot_state_clr = 1;
}
input_sync(dev);
HYN_INFO2("report keyid:%d keycode:%d",rep_frame->key_id,dt->key_code[rep_frame->key_id]);
}
if (rep_frame->report_need & REPORT_POS) { //pos
u8 i;
if (rep_frame->rep_num == 0) {
release_all_finger(ts_data);
reprot_state_clr = 1;
}
else{
u8 touch_down = 0;
ts_data->report_id_flg = 0;
for(i = 0; i < rep_frame->rep_num; i++) {
HYN_INFO2("id,%d,xy,%d,%d",rep_frame->pos_info[i].pos_id,rep_frame->pos_info[i].pos_x,rep_frame->pos_info[i].pos_y);
if (dt->swap_xy) {
xpos = rep_frame->pos_info[i].pos_y;
ypos = rep_frame->pos_info[i].pos_x;
}
else{
xpos = rep_frame->pos_info[i].pos_x;
ypos = rep_frame->pos_info[i].pos_y;
}
if (ypos > dt->y_resolution || xpos > dt->x_resolution) {
HYN_ERROR("Please check dts or FW config,maybe resolution or origin issue!!!");
}
if (rep_frame->pos_info[i].pos_id >= ts_data->plat_data.max_touch_num) {
continue;
}
if (dt->reverse_x) {
xpos = dt->x_resolution-xpos;
}
if (dt->reverse_y) {
ypos = dt->y_resolution-ypos;
}
rep_frame->pos_info[i].pos_x = xpos;
rep_frame->pos_info[i].pos_y = ypos;
touch_updata(i,rep_frame->pos_info[i].event? 1:0);
if (rep_frame->pos_info[i].event) touch_down++;
}
if (touch_down==0) {
reprot_state_clr = 1;
input_report_key(dev, BTN_TOUCH, 0);
#if HYN_MT_PROTOCOL_B_EN==0
input_mt_sync(dev);
#endif
}
}
input_sync(dev);
}
if (rep_frame->report_need & REPORT_PROX) {
hyn_proximity_report(ts_data->prox_state);
reprot_state_clr = 1;
}
#if (HYN_GESTURE_EN)
if (rep_frame->report_need & REPORT_GES) {
hyn_gesture_report(ts_data);
reprot_state_clr = 1;
}
#endif
if (reprot_state_clr) {
rep_frame->report_need = REPORT_NONE;
}
mutex_unlock(&ts_data->mutex_report);
}
static void hyn_esdcheck_work(struct work_struct *work)
{
#if ESD_CHECK_EN
int ret;
HYN_ENTER();
if (hyn_data->esd_block_cnt==0) {
ret = hyn_fun->tp_check_esd();
HYN_INFO("esd:%04x",ret);
if (hyn_data->esd_last_value != ret) {
hyn_data->esd_fail_cnt = 0;
hyn_data->esd_last_value = ret;
}
else{
hyn_data->esd_fail_cnt++;
if (hyn_data->esd_fail_cnt > 2) {
hyn_data->esd_fail_cnt = 0;
hyn_power_source_ctrl(hyn_data,0);
mdelay(1);
hyn_power_source_ctrl(hyn_data,1);
hyn_fun->tp_rest();
if (hyn_data->prox_is_enable) {
hyn_fun->tp_prox_handle(1);
}
else if (hyn_data->gesture_is_enable) {
hyn_fun->tp_set_workmode(GESTURE_MODE,1);
}
if (hyn_data->charge_is_enable) {
hyn_fun->tp_set_workmode(CHARGE_ENTER,1);
}
if (hyn_data->glove_is_enable) {
hyn_fun->tp_set_workmode(GLOVE_ENTER,1);
}
}
}
}
else{
hyn_data->esd_block_cnt--;
}
queue_delayed_work(hyn_data->hyn_workqueue, &hyn_data->esdcheck_work,
msecs_to_jiffies(1000));
#endif
}
static void hyn_resume(struct device *dev)
{
int ret = 0;
struct ts_frame *rep_frame;
struct hyn_plat_data *dt;
HYN_ENTER();
if (IS_ERR_OR_NULL(hyn_data)) {
return;
}
rep_frame = &hyn_data->rp_buf;
dt = &hyn_data->plat_data;
#if (HYN_WAKE_LOCK_EN==1)
wake_unlock(&hyn_data->tp_wakelock);
#endif
if (!IS_ERR_OR_NULL(dt->pinctl)) {
pinctrl_select_state(dt->pinctl, dt->pin_active);
}
hyn_power_source_ctrl(hyn_data, 1);
hyn_fun->tp_resum();
//Condition recovery
if (hyn_data->prox_is_enable) {
hyn_fun->tp_prox_handle(1);
} else if (hyn_data->gesture_is_enable) {
hyn_irq_set(hyn_data,DISABLE);
ret = disable_irq_wake(hyn_data->gpio_irq);
ret |= irq_set_irq_type(hyn_data->gpio_irq,dt->irq_flags);
if (ret < 0) {
HYN_ERROR("gesture disable_irq_wake failed");
}
}
if (hyn_data->charge_is_enable) {
hyn_fun->tp_set_workmode(CHARGE_ENTER,1);
}
if (hyn_data->glove_is_enable) {
hyn_fun->tp_set_workmode(GLOVE_ENTER,1);
}
//compensate for lifting
if (rep_frame->report_need & REPORT_KEY) {
input_report_key(hyn_data->input_dev,dt->key_code[rep_frame->key_id],0);
}
if (rep_frame->report_need & REPORT_POS) {
release_all_finger(hyn_data);
input_sync(hyn_data->input_dev);
}
rep_frame->report_need = REPORT_NONE;
hyn_irq_set(hyn_data,ENABLE);
}
static __maybe_unused void hyn_suspend(struct device *dev)
{
int ret = 0;
HYN_ENTER();
if (IS_ERR_OR_NULL(hyn_data)) {
return;
}
#if (HYN_WAKE_LOCK_EN==1)
wake_lock(&hyn_data->tp_wakelock);
#endif
if (hyn_data->prox_is_enable ==1) {
} else if (hyn_data->gesture_is_enable) {
hyn_irq_set(hyn_data,DISABLE);
ret = enable_irq_wake(hyn_data->gpio_irq);
ret |= irq_set_irq_type(hyn_data->gpio_irq,IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND|IRQF_ONESHOT);
if (ret < 0) {
HYN_ERROR("gesture irq_set_irq failed");
}
hyn_fun->tp_set_workmode(GESTURE_MODE,1);
hyn_irq_set(hyn_data,ENABLE);
hyn_power_source_ctrl(hyn_data, 1);
} else {
hyn_irq_set(hyn_data,DISABLE);
hyn_fun->tp_supend();
if (!IS_ERR_OR_NULL(hyn_data->plat_data.pinctl)) {
pinctrl_select_state(hyn_data->plat_data.pinctl, hyn_data->plat_data.pin_suspend);
}
hyn_power_source_ctrl(hyn_data, 0);
}
}
static void hyn_updata_fw_work(struct work_struct *work)
{
if (!IS_ERR_OR_NULL(hyn_data->fw_updata_addr)) {
hyn_fun->tp_updata_fw(hyn_data->fw_updata_addr,hyn_data->fw_updata_len);
}
else{
HYN_ERROR("fw_updata_addr is erro");
}
}
static void hyn_resume_work(struct work_struct *work)
{
if (IS_ERR_OR_NULL(hyn_data)) {
return;
}
hyn_resume(hyn_data->dev);
}
static irqreturn_t hyn_irq_handler(int irq, void *data)
{
atomic_set(&hyn_data->hyn_irq_flg,1);
if (hyn_data->work_mode < DIFF_MODE) {
// queue_work(hyn_data->hyn_workqueue,&hyn_data->work_report);
hyn_data->esd_block_cnt = 2;
flush_workqueue(hyn_data->hyn_workqueue);
hyn_irq_report_work(NULL);
}
else{
wake_up(&hyn_data->wait_irq);
}
return IRQ_HANDLED;
}
#if defined(CONFIG_FB)// || defined(CONFIG_DRM)
#ifndef FB_EARLY_EVENT_BLANK
#define FB_EARLY_EVENT_BLANK FB_EVENT_BLANK
#endif
static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
{
if (IS_ERR_OR_NULL(data)) {
HYN_INFO("data is invlid don't handle");
return 0;
}
{
#if defined(CONFIG_FB)
int blank_value = *((int *)(((struct fb_event *)data)->data));
const unsigned long event_enum[2] = {FB_EARLY_EVENT_BLANK, FB_EVENT_BLANK};
const int blank_enum[2] = {FB_BLANK_POWERDOWN, FB_BLANK_UNBLANK};
// #elif defined(CONFIG_DRM)
// #if defined(CONFIG_DRM_PANEL)
// int blank_value = *((int *)(((struct drm_panel_notifier *)data)->data));
// const unsigned long event_enum[2] = {DRM_PANEL_EARLY_EVENT_BLANK, DRM_PANEL_EVENT_BLANK};
// const int blank_enum[2] = {DRM_PANEL_BLANK_POWERDOWN, DRM_PANEL_BLANK_UNBLANK};
// #else //CONFIG_DRM_PANEL
// int blank_value = *((int *)(((struct msm_drm_notifier *)data)->data));
// const unsigned long event_enum[2] = {MSM_DRM_EARLY_EVENT_BLANK, MSM_DRM_EVENT_BLANK};
// const int blank_enum[2] = {MSM_DRM_BLANK_POWERDOWN, MSM_DRM_BLANK_UNBLANK};
// #endif //CONFIG_DRM_PANEL
#endif //CONFIG_DRM
HYN_INFO("notifier,event:%lu,blank:%d", event, blank_value);
if (hyn_data->old_fb_state == blank_value || (event != event_enum[0] && event != event_enum[1])) {
HYN_INFO("don't care");
return 0;
}
if (blank_enum[1] == blank_value) {
queue_work(hyn_data->hyn_workqueue, &hyn_data->work_resume);
} else{
cancel_work_sync(&hyn_data->work_resume);
hyn_suspend(hyn_data->dev);
}
hyn_data->old_fb_state = blank_value;
return 0;
}
}
#elif defined(CONFIG_HAS_EARLYSUSPEND)
static void hyn_ts_early_suspend(struct early_suspend *handler)
{
hyn_suspend(hyn_data->dev);
}
static void hyn_ts_late_resume(struct early_suspend *handler)
{
hyn_resume(hyn_data->dev);
}
#endif
#ifdef I2C_PORT
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
static void hyn_ts_remove(struct i2c_client *client);
#else
static int hyn_ts_remove(struct i2c_client *client);
#endif
static int hyn_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
#else
#ifdef CONFIG_BUS_SPI
static struct mt_chip_conf hyn_mt_spi_conf = {
.setuptime = 100,
.holdtime = 100,
.high_time = 25,
.low_time = 25,
.cs_idletime = 2,
.ulthgh_thrsh = 0,
.cpol = 0,
.cpha = 0,
.rx_mlsb = 1,
.tx_mlsb = 1,
.tx_endian = 0,
.rx_endian = 0,
.com_mod = DMA_TRANSFER,/*FIFO_TRANSFER,*/
.pause = 1, /*0 : twice cs 1: one cs*/
.finish_intr = 1,
.deassert = 0,
.ulthigh = 0,
.tckdly = 0,
};
#endif
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
static void hyn_ts_remove(struct spi_device *client);
#else
static int hyn_ts_remove(struct spi_device *client);
#endif
static int hyn_ts_probe(struct spi_device *client)
#endif
{
int ret = 0;
u16 bus_type;
struct hyn_ts_data *ts_data = 0;
HYN_ENTER();
HYN_INFO(HYN_DRIVER_VERSION);
#ifdef I2C_PORT
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
HYN_ERROR("I2C not supported");
return -ENODEV;
}
bus_type = BUS_I2C;
#else
client->mode = SPI_MODE;
client->max_speed_hz = SPI_CLOCK_FREQ;
client->bits_per_word = 8;
#ifdef CONFIG_BUS_SPI
client->controller_data = (void *)&hyn_mt_spi_conf;
#endif
if (spi_setup(client) < 0) {
HYN_ERROR("SPI not supported");
return -ENODEV;
}
bus_type = BUS_SPI;
#endif
if (!IS_ERR_OR_NULL(hyn_data)) {
HYN_ERROR("other dev is insmode");
return -ENOMEM;
}
ts_data = kzalloc(sizeof(*ts_data), GFP_KERNEL);
if (!ts_data) {
HYN_ERROR("alloc ts data failed");
return -ENOMEM;
}
ts_data->bus_type = bus_type;
ts_data->rp_buf.key_id = 0xFF;
ts_data->work_mode = NOMAL_MODE;
ts_data->log_level = 0;
hyn_data = ts_data;
ts_data->client = client;
ts_data->dev = &client->dev;
dev_set_drvdata(ts_data->dev, ts_data);
#if (I2C_USE_DMA==2)
ts_data->dev->coherent_dma_mask = DMA_BIT_MASK(32);
ts_data->dma_buff_va = (u8 *)dma_alloc_coherent(ts_data->dev,
2048, &ts_data->dma_buff_pa, GFP_KERNEL);
if (!ts_data->dma_buff_va) {
HYN_ERROR("Allocate I2C DMA Buffer fail");
}
#endif
ret = hyn_parse_dt(ts_data);
if (ret) {
HYN_ERROR("hyn_parse_dt failed");
goto FREE_RESOURCE;
}
ret = hyn_poweron(ts_data);
if (ret) {
HYN_ERROR("hyn_poweron failed");
goto FREE_RESOURCE;
}
// spin_lock_init(&ts_data->irq_lock);
mutex_init(&ts_data->mutex_report);
mutex_init(&ts_data->mutex_bus);
mutex_init(&ts_data->mutex_fs);
init_waitqueue_head(&ts_data->wait_irq);
ret = hyn_check_ic(ts_data);
if (ret) {
HYN_ERROR("hyn_check_ic failed");
goto FREE_RESOURCE;
}
INIT_WORK(&ts_data->work_report,hyn_irq_report_work);
INIT_WORK(&ts_data->work_updata_fw,hyn_updata_fw_work);
INIT_WORK(&ts_data->work_resume,hyn_resume_work);
INIT_DELAYED_WORK(&ts_data->esdcheck_work,hyn_esdcheck_work);
ts_data->hyn_workqueue = create_singlethread_workqueue("hyn_wq");
if (IS_ERR_OR_NULL(ts_data->hyn_workqueue)) {
HYN_ERROR("create work queue failed");
ret = -ENOMEM;
goto FREE_RESOURCE;
}
ret = hyn_input_dev_init(ts_data);
if (ret) {
if (!IS_ERR_OR_NULL(ts_data->input_dev)) {
input_set_drvdata(ts_data->input_dev, NULL);
input_free_device(ts_data->input_dev);
ts_data->input_dev = NULL;
}
HYN_ERROR("hyn_input_dev_init failed");
goto FREE_RESOURCE;
}
ret = input_register_device(ts_data->input_dev);
if (ret) {
HYN_ERROR("input_register_device failed");
goto FREE_RESOURCE;
}
#if (HYN_WAKE_LOCK_EN==1)
wake_lock_init(&ts_data->tp_wakelock, WAKE_LOCK_SUSPEND, "suspend_tp_lock");
#endif
#if (HYN_GESTURE_EN)
ret = hyn_gesture_init(ts_data);
if (ret) {
HYN_ERROR("gesture_init failed");
goto FREE_RESOURCE;
}
#endif
ts_data->gpio_irq = gpiod_to_irq(ts_data->plat_data.irq_gpio);
if (ts_data->gpio_irq < 0) {
HYN_ERROR("failed to get gpio irq\n");
ret = ts_data->gpio_irq;
goto FREE_RESOURCE;
}
ts_data->plat_data.irq_flags = irqd_get_trigger_type(irq_get_irq_data(ts_data->gpio_irq));
ret = devm_request_threaded_irq(ts_data->dev, ts_data->gpio_irq, NULL, hyn_irq_handler,
(IRQF_TRIGGER_FALLING | IRQF_ONESHOT), HYN_DRIVER_NAME,
ts_data);
if (ret) {
HYN_ERROR("devm_request_threaded_irq failed");
goto FREE_RESOURCE;
}
atomic_set(&ts_data->irq_is_disable,ENABLE);
hyn_irq_set(ts_data , DISABLE);
#if defined(CONFIG_FB)
HYN_INFO("fb_notif_register");
ts_data->fb_notif.notifier_call = fb_notifier_callback;
ret = fb_register_client(&ts_data->fb_notif);
if (ret) {
HYN_ERROR("register fb_notifier failed: %d", ret);
}
// #elif defined(CONFIG_DRM)
// ts_data->fb_notif.notifier_call = fb_notifier_callback;
// #if defined(CONFIG_DRM_PANEL)
// HYN_INFO("drm_panel register");
// {
// int i,count;
// struct device_node *node;
// struct drm_panel *panel;
// struct device_node *np = ts_data->dev->of_node;
// count = of_count_phandle_with_args(np, "panel", NULL);
// ts_data->active_panel = NULL;
// if (count > 0) {
// for (i = 0; i < count; i++) {
// node = of_parse_phandle(np, "panel", i);
// panel = of_drm_find_panel(node);
// of_node_put(node);
// if (!IS_ERR(panel)) {
// ts_data->active_panel = panel;
// break;
// }
// }
// }
// if (IS_ERR_OR_NULL(ts_data->active_panel)) {
// HYN_ERROR("node can't not find DRM panel ");
// }
// }
// if (!IS_ERR_OR_NULL(ts_data->active_panel)) {
// ret = drm_panel_notifier_register(ts_data->active_panel,&ts_data->fb_notif);
// if (ret < 0) {
// HYN_ERROR("drm_panel_notifier_register failed: %d", ret);
// }
// }
// #else
// HYN_INFO("msm_drm_register");
// ret = msm_drm_register_client(&ts_data->fb_notif);
// if (ret < 0) {
// HYN_ERROR("msm_drm_register_client failed: %d", ret);
// }
// #endif
#elif defined(CONFIG_HAS_EARLYSUSPEND)
ts_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
ts_data->early_suspend.suspend = hyn_ts_early_suspend;
ts_data->early_suspend.resume = hyn_ts_late_resume;
register_early_suspend(&ts_data->early_suspend);
#endif
hyn_create_sysfs(ts_data);
#if (HYN_APK_DEBUG_EN)
hyn_tool_fs_int(ts_data);
#endif
hyn_proximity_int(ts_data);
hyn_irq_set(ts_data,ENABLE);
hyn_esdcheck_switch(ts_data,ENABLE);
#if HYN_POWER_ON_UPDATA
if (ts_data->need_updata_fw) {
queue_work(ts_data->hyn_workqueue,&ts_data->work_updata_fw);
}
#endif
return 0;
FREE_RESOURCE:
hyn_ts_remove(client);
return ret;
}
#ifdef I2C_PORT
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
static void hyn_ts_remove(struct i2c_client *client)
#else
static int hyn_ts_remove(struct i2c_client *client)
#endif
#else
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
static void hyn_ts_remove(struct spi_device *client)
#else
static int hyn_ts_remove(struct spi_device *client)
#endif
#endif
{
struct hyn_ts_data *ts_data = hyn_data;
HYN_ENTER();
if (!IS_ERR_OR_NULL(ts_data)) {
if (ts_data->hyn_workqueue) {
flush_workqueue(ts_data->hyn_workqueue);
hyn_esdcheck_switch(ts_data,DISABLE);
destroy_workqueue(ts_data->hyn_workqueue);
}
HYN_INFO("ts_remove1");
#if (HYN_APK_DEBUG_EN)
hyn_tool_fs_exit();
#endif
hyn_proximity_exit();
#if (HYN_GESTURE_EN)
hyn_gesture_exit(ts_data);
#endif
hyn_release_sysfs(ts_data);
HYN_INFO("ts_remove2");
if (!IS_ERR_OR_NULL(ts_data->input_dev)) {
input_unregister_device(ts_data->input_dev);
}
HYN_INFO("ts_remove3");
#if 0
#if defined(CONFIG_FB)
fb_unregister_client(&ts_data->fb_notif);
// #elif defined(CONFIG_DRM)
// #if defined(CONFIG_DRM_PANEL)
// if (!IS_ERR_OR_NULL(ts_data->active_panel))
// drm_panel_notifier_unregister(ts_data->active_panel, &ts_data->fb_notif);
// #else
// msm_drm_unregister_client(&ts_data->fb_notif);
// #endif
#elif defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&ts_data->early_suspend);
#endif
#endif
hyn_power_source_ctrl(hyn_data, 0);
if (!IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)) {
regulator_put(ts_data->plat_data.vdd_ana);
}
if (!IS_ERR_OR_NULL(ts_data->plat_data.vdd_i2c)) {
regulator_put(ts_data->plat_data.vdd_i2c);
}
HYN_INFO("ts_remove4");
#if (I2C_USE_DMA==2)
if (!IS_ERR_OR_NULL(ts_data->dma_buff_va)) {
dma_free_coherent(NULL, 2048, ts_data->dma_buff_va, ts_data->dma_buff_pa);
}
#endif
kfree(ts_data);
hyn_data = NULL;
HYN_INFO("ts_remove5");
}
#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
return 0;
#endif
}
#ifdef I2C_PORT
static const struct i2c_device_id hyn_id_table[] = {
{.name = HYN_DRIVER_NAME, .driver_data = 0,},
{},
};
static struct i2c_driver hyn_ts_driver = {
.probe = hyn_ts_probe,
.remove = hyn_ts_remove,
.driver = {
.name = HYN_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = hyn_of_match_table,
},
.id_table = hyn_id_table,
};
#else
static struct spi_driver hyn_ts_driver = {
.driver = {
.name = HYN_DRIVER_NAME,
.of_match_table = hyn_of_match_table,
.owner = THIS_MODULE,
},
.probe = hyn_ts_probe,
.remove = hyn_ts_remove,
};
#endif
static int __init hyn_ts_init(void)
{
int ret = 0;
HYN_ENTER();
#ifdef I2C_PORT
ret = i2c_add_driver(&hyn_ts_driver);
#else
ret = spi_register_driver(&hyn_ts_driver);
#endif
if (ret) {
HYN_ERROR("add i2c driver failed");
return -ENODEV;
}
return 0;
}
static void __exit hyn_ts_exit(void)
{
HYN_ENTER();
#ifdef I2C_PORT
i2c_del_driver(&hyn_ts_driver);
#else
spi_unregister_driver(&hyn_ts_driver);
#endif
}
late_initcall(hyn_ts_init);
// module_init(hyn_ts_init);
module_exit(hyn_ts_exit);
MODULE_AUTHOR("Hynitron Driver Team");
MODULE_DESCRIPTION("Hynitron Touchscreen Driver");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,385 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_core.h
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef HYNITRON_CORE_H
#define HYNITRON_CORE_H
#include <linux/syscalls.h>
#include <linux/gpio.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/dma-mapping.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/kthread.h>
#include <linux/kernel.h>
//#include <linux/rtpm_prio.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/pm_wakeup.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/fb.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
// #include <linux/regulator/driver.h>
#include <linux/sysfs.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/moduleparam.h>
#include "hyn_cfg.h"
#ifdef CONFIG_BUS_SPI
#include "mt_spi.h"
#endif
#if (HYN_WAKE_LOCK_EN == 1)
#include <linux/wakelock.h>
#endif
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
// #elif defined(CONFIG_DRM)
// #include <linux/msm_drm_notify.h>
// #if defined(CONFIG_DRM_PANEL)
// #include <drm/drm_panel.h>
// #endif
#elif defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
#endif
// #define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
#define HYN_INFO(fmt, args...) printk(KERN_INFO "[HYN]"fmt"\n", ##args)
#define HYN_INFO2(fmt, args...) if(hyn_data->log_level > 0)printk(KERN_INFO "[HYN]"fmt"\n", ##args)
#define HYN_INFO3(fmt, args...) if(hyn_data->log_level > 1)printk(KERN_INFO "[HYN]"fmt"\n", ##args)
#define HYN_INFO4(fmt, args...) if(hyn_data->log_level > 2)printk(KERN_INFO "[HYN]"fmt"\n", ##args)
#define HYN_ERROR(fmt, args...) printk(KERN_ERR "[HYN][Error]%s:"fmt"\n",__func__,##args)
#define HYN_ENTER() printk(KERN_ERR "[HYN][enter]%s\n",__func__)
#if HYN_GKI_VER
// MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
#endif
// #define IS_ERR_OR_NULL(x) (x <= 0)
#define U8TO16(x1,x2) ((((x1)&0xFF)<<8)|((x2)&0xFF))
#define U8TO32(x1,x2,x3,x4) ((((x1)&0xFF)<<24)|(((x2)&0xFF)<<16)|(((x3)&0xFF)<<8)|((x4)&0xFF))
#define U16REV(x) ((((x)<<8)&0xFF00)|(((x)>>8)&0x00FF))
#undef NULL
#undef FALSE
#undef TRUE
#undef DISABLE
#undef ENABLE
#define NULL ((void*)0)
#define FALSE (-1)
#define TRUE (0)
#define DISABLE (0)
#define ENABLE (1)
#define PS_FAR_AWAY 1
#define PS_NEAR 0
#define MULTI_OPEN_TEST (0x80)
#define MULTI_SHORT_TEST (0x01)
#define MULTI_SCAP_TEST (0x02)
#if HYN_GKI_VER
#define hyn_fs_write(...)
#define hyn_fs_read(...)
#else
#define hyn_fs_write kernel_write
#define hyn_fs_read kernel_read
#endif
enum work_mode{
NOMAL_MODE = 0,
GESTURE_MODE = 1,
LP_MODE = 2,
DEEPSLEEP = 3,
DIFF_MODE = 4,
RAWDATA_MODE = 5,
BASELINE_MODE = 6,
CALIBRATE_MODE = 7,
FAC_TEST_MODE = 8,
GLOVE_EXIT = 0x10,
GLOVE_ENTER = 0x11,
CHARGE_EXIT = 0x12,
CHARGE_ENTER = 0x13,
ENTER_BOOT_MODE = 0xCA,
};
enum report_typ{
REPORT_NONE = 0,
REPORT_POS = 0x01,
REPORT_KEY = 0x02,
REPORT_GES = 0x04,
REPORT_PROX = 0x08
};
enum fac_test_ero{
FAC_TEST_PASS = 0,
FAC_GET_DATA_FAIL = -1,
FAC_GET_CFG_FAIL = -4,
FAC_TEST_OPENL_FAIL = -5,
FAC_TEST_OPENH_FAIL = -7,
FAC_TEST_SHORT_FAIL = -6,
FAC_TEST_SCAP_FAIL = -8,
};
enum ges_idx{
IDX_U = 0,
IDX_UP,
IDX_DOWN,
IDX_LEFT,
IDX_RIGHT,
IDX_O,
IDX_e,
IDX_M,
IDX_L,
IDX_W,
IDX_S,
IDX_V,
IDX_C,
IDX_Z,
IDX_POWER,
IDX_NULL = 0xFF,
};
struct hyn_plat_data {
struct regulator *vdd_ana;
struct regulator *vdd_i2c;
struct gpio_desc *reset_gpio;
struct gpio_desc *irq_gpio;
unsigned long irq_flags;
struct pinctrl *pinctl;
struct pinctrl_state *pin_active;
struct pinctrl_state *pin_suspend;
u32 x_resolution;
u32 y_resolution;
int swap_xy;
int reverse_x;
int reverse_y;
int max_touch_num;
int key_num;
u32 key_x_coords[8]; // max support 8 keys
u32 key_y_coords;
u32 key_code[8];
};
struct hyn_chip_series {
u32 part_no;
u32 moudle_id;
u8* chip_name;
u8* fw_bin;
};
#define MAX_POINTS_REPORT (10)
struct ts_frame {
u8 rep_num;
enum report_typ report_need;
u8 key_id;
u8 key_state;
struct {
u8 pos_id;
u8 event;
u16 pos_x;
u16 pos_y;
u16 pres_z;
} pos_info[MAX_POINTS_REPORT];
};
struct tp_info {
u8 fw_sensor_txnum;
u8 fw_sensor_rxnum;
u8 fw_key_num;
u8 reserve;
u16 fw_res_y;
u16 fw_res_x;
u32 fw_boot_time;
u32 fw_project_id;
u32 fw_chip_type;
u32 fw_ver;
u32 ic_fw_checksum;
u32 fw_module_id;
};
struct hyn_ts_data {
u16 bus_type;
#ifdef I2C_PORT
struct i2c_client *client;
#else
struct spi_device *client;
#endif
struct device *dev;
struct input_dev *input_dev;
struct workqueue_struct *hyn_workqueue;
int gpio_irq;
int esd_fail_cnt;
u32 esd_last_value;
int esd_block_cnt;
int report_id_flg;
enum work_mode work_mode;
int power_is_on;
atomic_t irq_is_disable;
atomic_t hyn_irq_flg;
// spinlock_t irq_lock;
struct mutex mutex_report;
struct mutex mutex_bus;
struct mutex mutex_fs;
#if (HYN_WAKE_LOCK_EN==1)
struct wake_lock tp_wakelock;
#endif
#if (I2C_USE_DMA==2)
u8 *dma_buff_va;
dma_addr_t dma_buff_pa;
#endif
struct hyn_plat_data plat_data;
struct tp_info hw_info;
struct ts_frame rp_buf;
struct work_struct work_report;
struct work_struct work_resume;
struct delayed_work esdcheck_work;
struct work_struct work_updata_fw;
int boot_is_pass;
int need_updata_fw;
u8 fw_file_name[128];
u8 *fw_updata_addr;
int fw_updata_len;
int fw_dump_state;
u8 fw_updata_process;
u8 host_cmd_save[16];
wait_queue_head_t wait_irq;
u8 log_level;
u8 prox_is_enable;
u8 prox_state;
u8 gesture_is_enable;
u8 gesture_id;
const void *hyn_fuc_used;
u8 charge_is_enable;
u8 glove_is_enable;
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
int old_fb_state;
// #elif defined(CONFIG_DRM)
// struct notifier_block fb_notif;
// int old_fb_state;
// #if defined(CONFIG_DRM_PANEL)
// struct drm_panel *active_panel;
// #endif
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
struct kobject *sys_node;
};
struct hyn_ts_fuc{
void (*tp_rest)(void);
int (*tp_report)(void);
int (*tp_supend)(void);
int (*tp_resum)(void);
int (*tp_chip_init)(struct hyn_ts_data *ts_data);
int (*tp_updata_fw)(u8 *bin_addr, u16 len);
int (*tp_set_workmode)(enum work_mode mode,u8 enable);
u32 (*tp_check_esd)(void);
int (*tp_prox_handle)(u8 cmd);
int (*tp_get_dbg_data)(u8 *buf,u16 len);
int (*tp_get_test_result)(u8 *buf,u16 len);
};
int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len);
int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len);
int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen);
void hyn_irq_set(struct hyn_ts_data *ts_data, u8 value);
void hyn_esdcheck_switch(struct hyn_ts_data *ts_data, u8 enable);
int hyn_copy_for_updata(struct hyn_ts_data *ts_data,u8 *buf,u32 offset,u16 len);
int hyn_get_word(u8 **sc_str, u8* ds_str);
void hyn_set_i2c_addr(struct hyn_ts_data *ts_data,u8 addr);
int hyn_proc_fs_int(struct hyn_ts_data *ts_data);
void hyn_proc_fs_exit(void);
int hyn_tool_fs_int(struct hyn_ts_data *ts_data);
void hyn_tool_fs_exit(void);
int hyn_create_sysfs(struct hyn_ts_data *ts_data);
void hyn_release_sysfs(struct hyn_ts_data *ts_data);
int hyn_gesture_init(struct hyn_ts_data *ts_data);
void hyn_gesture_report(struct hyn_ts_data *ts_data);
void hyn_gesture_exit(struct hyn_ts_data *ts_data);
int hyn_proximity_exit(void);
int hyn_proximity_int(struct hyn_ts_data *ts_data);
int hyn_proximity_report(u8 proximity_value);
int hyn_wait_irq_timeout(struct hyn_ts_data *ts_data,int msec);
int hyn_factory_multitest(struct hyn_ts_data *ts_data ,char *cfg_path, u8 *data,s16 *test_th,u8 test_item);
int hyn_fac_test_log_save(char *log_name,struct hyn_ts_data *ts_data,s16 *test_data, int test_ret, u8 test_item);
int hyn_str_2_num(char *str,u8 type);
u16 hyn_sum16(int val, u8* buf,u16 len);
u32 hyn_sum32(int val, u32* buf,u16 len);
int hyn_power_source_ctrl(struct hyn_ts_data *ts_data, int enable);
//ic type
extern const struct hyn_ts_fuc hyn_cst3xx_fuc;
extern const struct hyn_ts_fuc hyn_cst66xx_fuc;
extern const struct hyn_ts_fuc hyn_cst7xx_fuc;
extern const struct hyn_ts_fuc hyn_cst8xxT_fuc;
extern const struct hyn_ts_fuc hyn_cst92xx_fuc;
extern const struct hyn_ts_fuc hyn_cst3240_fuc;
extern const struct hyn_ts_fuc hyn_cst226se_fuc;
extern const struct hyn_ts_fuc hyn_cst36xxes_fuc;
#endif

View File

@@ -0,0 +1,345 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_fs_node.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#include <linux/string.h>
#include <linux/kernel.h>
static struct hyn_ts_data *hyn_fs_data = NULL;
//echo fd /sdcard/app.bin
//echo w d1 01
//echo w d1 01 r 2
//echo w 1 2 3 4 5
//echo rst
#define DEBUG_BUF_SIZE (256)
static ssize_t hyn_dbg_show(struct device *dev,struct device_attribute *attr,char *buf)
{
ssize_t len = 0;
int ret = -1;
u8 *kbuf =NULL;
u16 i;
HYN_ENTER();
mutex_lock(&hyn_fs_data->mutex_fs);
kbuf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL);
if(hyn_fs_data->host_cmd_save[0]==0x5A){
if(hyn_fs_data->host_cmd_save[1] > 4) hyn_fs_data->host_cmd_save[1] = 4;
len = hyn_fs_data->host_cmd_save[6];
if(len != 0 && hyn_fs_data->host_cmd_save[1] !=0){
u32 reg;
reg = hyn_fs_data->host_cmd_save[2];
i = 0;
while(++i < hyn_fs_data->host_cmd_save[1]){
reg <<= 8;
reg |= hyn_fs_data->host_cmd_save[2+i];
}
ret = hyn_wr_reg(hyn_fs_data,reg,hyn_fs_data->host_cmd_save[1],kbuf,(u16)len);
}
}
else if(hyn_fs_data->host_cmd_save[0]==0x7A){
len = hyn_fs_data->host_cmd_save[6];
ret = hyn_read_data(hyn_fs_data,kbuf,(u16)len);
}
if(ret ==0){
ssize_t cnt_char = 0;
for(i = 0; i< len; i++){
ret = sprintf(buf+cnt_char,"0x%02x ",*(kbuf+i));
cnt_char += ret;
}
buf[cnt_char] = '\n';
ret = cnt_char+1;
}
else{
sprintf(buf,"fs read failed\n");
ret = 13;
}
if(!IS_ERR_OR_NULL(kbuf)) kfree(kbuf);
mutex_unlock(&hyn_fs_data->mutex_fs);
return ret;
}
static ssize_t hyn_dbg_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
u16 rec_len;
u8 str[128];
u8 *next_ptr;
int val;
const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used;
int ret = 0;
HYN_ENTER();
mutex_lock(&hyn_fs_data->mutex_fs);
rec_len = strlen(buf);
HYN_INFO("rec_len =%d",rec_len);
// HYN_INFO("%ddata:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",(int)count,buf[0], buf[1],buf[2], buf[3],buf[4], buf[5],buf[6],buf[7]);
if(rec_len < 1 || rec_len > DEBUG_BUF_SIZE){
HYN_INFO("erro write len");
goto END;
}
next_ptr = (u8*)buf;
str[0] = '\0';
hyn_get_word(&next_ptr,str);
if(0 == strcmp(str,"fd")){ //updata fw
hyn_get_word(&next_ptr,str);
if(strlen(str)<4){
strcpy(str,"/sdcard/app.bin");
}
HYN_INFO("filename = %s",str);
strcpy(hyn_fs_data->fw_file_name,str);
hyn_fun->tp_updata_fw(hyn_fs_data->fw_updata_addr,hyn_fs_data->fw_updata_len);
// if(0 == hyn_read_fw_file(str, &pdata, &bin_len)){
// ret = hyn_fun->tp_updata_fw(pdata,bin_len);
// kfree(pdata);
// }
}
else if(0 == strcmp(str,"w")){
u8 i = 0;
u8 *kbuf = kzalloc(count/2, GFP_KERNEL);
hyn_fs_data->host_cmd_save[0] = 0;
hyn_fs_data->host_cmd_save[1] = 0xA5;
hyn_fs_data->host_cmd_save[6] = 0;
while(1){
str[0] = '\0';
ret = hyn_get_word(&next_ptr,str);
// next_ptr += ret;
HYN_INFO("read =%s ,len =%d",str,(int)strlen(str));
if(0 == strcmp(str,"r")){
ret = hyn_get_word(&next_ptr,str);
val = hyn_str_2_num(str,16);
if(ret < 0x100){
hyn_fs_data->host_cmd_save[0] = 0x5A;
hyn_fs_data->host_cmd_save[1] = i>4 ? 4:i;
hyn_fs_data->host_cmd_save[6] = val;
memcpy(&hyn_fs_data->host_cmd_save[2],kbuf,4);
i = 0;
}
break;
}
if(ret == 0 || strlen(str)==0 || strlen(str)>2){
break;
}
val = hyn_str_2_num(str,16);
if(val > 0xFF) break;
*(kbuf+i) = val;
HYN_INFO(" %02x",val);
i++;
}
if(i){
hyn_write_data(hyn_fs_data,kbuf,2,i);
}
kfree(kbuf);
}
else if(0 == strcmp(str,"r")){
hyn_get_word(&next_ptr,str);
val = hyn_str_2_num(str,16);
if(val < 0x100){
hyn_fs_data->host_cmd_save[0] = 0x7A;
hyn_fs_data->host_cmd_save[6] = val;
}
}
else if(0 == strcmp(str,"rst")){
hyn_fun->tp_rest();
}
else if(0 == strcmp(str,"log")){
hyn_get_word(&next_ptr,str);
hyn_fs_data->log_level = (u8)(str[0]-'0');
}
else if(0 == strcmp(str,"workmode")){
ret = hyn_get_word(&next_ptr,str);
if(ret){
u8 mode = (u8)(str[0]-'0');
ret = hyn_get_word(&next_ptr,str);
if(ret) hyn_fun->tp_set_workmode(mode,str[0]=='0'? 0:1);
}
}
END:
mutex_unlock(&hyn_fs_data->mutex_fs);
return count;
}
/////
///cat hyntpfwver
static ssize_t hyn_tpfwver_show(struct device *dev, struct device_attribute *attr,char *buf)
{
ssize_t num_read = 0;
HYN_ENTER();
num_read = snprintf(buf, 128, "fw_version:0x%02X,chip_type:0x%02X,checksum:0x%02X,project_id:%04x\n",
hyn_fs_data->hw_info.fw_ver,
hyn_fs_data->hw_info.fw_chip_type,
hyn_fs_data->hw_info.ic_fw_checksum,
hyn_fs_data->hw_info.fw_project_id
);
return num_read;
}
static ssize_t hyn_tpfwver_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
/*place holder for future use*/
return -EPERM;
}
///cat hynselftest
static ssize_t hyn_selftest_show(struct device *dev, struct device_attribute *attr,char *buf)
{
ssize_t num_read = 0;
u8 *rbuf = NULL;
const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used;
int ret = 0;
int max_len = hyn_fs_data->hw_info.fw_sensor_rxnum*hyn_fs_data->hw_info.fw_sensor_txnum*2
+ (hyn_fs_data->hw_info.fw_sensor_rxnum + hyn_fs_data->hw_info.fw_sensor_txnum)*4;
HYN_ENTER();
max_len = max_len*3;
rbuf = kzalloc(max_len, GFP_KERNEL);
if(rbuf == NULL){
HYN_ERROR("zalloc GFP_KERNEL memory[%d] failed.\n",max_len);
return -ENOMEM;
}
hyn_fun->tp_set_workmode(FAC_TEST_MODE,0);
ret = hyn_fun->tp_get_test_result(rbuf,max_len);
num_read = snprintf(buf, 128, "module selftest %s ret:%d\r\n",
ret==0 ? "pass":"failed", ret);
if(!IS_ERR_OR_NULL(rbuf)){
kfree(rbuf);
}
return num_read;
}
static ssize_t hyn_selftest_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
/*place reserver*/
return -EPERM;
}
//hyndumpfw
static ssize_t hyn_dumpfw_show(struct device *dev,struct device_attribute *attr,char *buf)
{
HYN_ENTER();
return (ssize_t)snprintf(buf, 128, "place reserver");
}
static ssize_t hyn_dumpfw_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
u8 str[16]={'\0'};
int max_len = hyn_fs_data->fw_updata_len+64;
if(count<10){
memcpy(str,buf,count);
if(str[count-1]==0x0A) str[count-1] = '\0';
}
// HYN_INFO("state[%d]: %d,%s",(int)count,hyn_fs_data->fw_dump_state,str);
if(0 == strcmp(str,"fwstart")){
hyn_fs_data->fw_dump_state = 0;
hyn_fs_data->fw_updata_addr = vmalloc(max_len);
if(hyn_fs_data->fw_updata_addr == NULL){
HYN_ERROR("vmalloc memory[%d] failed.\n",max_len);
hyn_fs_data->fw_dump_state=-1;
return -EPERM;
}
else{
HYN_INFO("vmalloc memory[%d] success",max_len);
}
}
else if(0 == strcmp(str,"fwend")){
if(hyn_fs_data->fw_dump_state >= 0){
const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used;
memset(hyn_fs_data->fw_file_name,0,sizeof(hyn_fs_data->fw_file_name));
hyn_fun->tp_updata_fw(hyn_fs_data->fw_updata_addr,hyn_fs_data->fw_updata_len);
vfree(hyn_fs_data->fw_updata_addr);
}
hyn_fs_data->fw_dump_state = -2;
}
else if(hyn_fs_data->fw_dump_state >=0 && (hyn_fs_data->fw_dump_state + count) < max_len){
memcpy(hyn_fs_data->fw_updata_addr+hyn_fs_data->fw_dump_state,buf,count);
hyn_fs_data->fw_dump_state += count;
}
return count;
}
/////
///cat hyntpfwver
static ssize_t hyn_mode_show(struct device *dev, struct device_attribute *attr,char *buf)
{
ssize_t num_read = 0;
HYN_ENTER();
num_read = snprintf(buf, 128, "is_charge:%d, is_glove:%d",hyn_fs_data->charge_is_enable,hyn_fs_data->glove_is_enable);
return num_read;
}
static ssize_t hyn_mode_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used;
HYN_ENTER();
HYN_INFO("wlen:%d,%c%c",(int)count,buf[0],buf[1]);
if(buf[0]=='c' || buf[0]=='C'){
hyn_fun->tp_set_workmode(buf[1]=='1' ? CHARGE_ENTER:CHARGE_EXIT,1);
}
else if(buf[0]=='g' || buf[0]=='G'){
hyn_fun->tp_set_workmode(buf[1]=='1' ? GLOVE_ENTER:GLOVE_EXIT,1);
}
return count;
}
static DEVICE_ATTR(hyntpfwver, S_IRUGO | S_IWUSR, hyn_tpfwver_show, hyn_tpfwver_store);
static DEVICE_ATTR(hyntpdbg, S_IRUGO | S_IWUSR, hyn_dbg_show, hyn_dbg_store);
static DEVICE_ATTR(hynselftest, S_IRUGO | S_IWUSR, hyn_selftest_show, hyn_selftest_store);
static DEVICE_ATTR(hyndumpfw, S_IRUGO | S_IWUSR, hyn_dumpfw_show, hyn_dumpfw_store);
static DEVICE_ATTR(hynswitchmode, S_IRUGO | S_IWUSR, hyn_mode_show, hyn_mode_store);
static struct attribute *hyn_attributes[] = {
&dev_attr_hynswitchmode.attr,
&dev_attr_hyndumpfw.attr,
&dev_attr_hyntpdbg.attr,
&dev_attr_hynselftest.attr,
&dev_attr_hyntpfwver.attr,
NULL
};
static struct attribute_group hyn_attribute_group = {
.attrs = hyn_attributes
};
int hyn_create_sysfs(struct hyn_ts_data *ts_data)
{
int ret = 0;
hyn_fs_data = ts_data;
hyn_fs_data->fw_dump_state = -1;
ts_data->sys_node = &ts_data->dev->kobj;//kobject_create_and_add("hynitron_debug", NULL);
if(IS_ERR_OR_NULL(ts_data->sys_node)){
HYN_ERROR("kobject_create_and_add failed");
return -1;
}
ret = sysfs_create_group(ts_data->sys_node, &hyn_attribute_group);
// if(ret){
// kobject_put(ts_data->sys_node);
// return -1;
// }
HYN_INFO("sys_node creat success ,GKI version is [%s]",HYN_GKI_VER ? "enable":"disable");
return ret;
}
void hyn_release_sysfs(struct hyn_ts_data *ts_data)
{
if(!IS_ERR_OR_NULL(ts_data->sys_node)){
sysfs_remove_group(ts_data->sys_node, &hyn_attribute_group);
//kobject_put(ts_data->sys_node);
ts_data->sys_node = NULL;
}
}

View File

@@ -0,0 +1,106 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_gesture.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
static const u8 gesture_key[] = {KEY_U,KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT,
KEY_O,KEY_E, KEY_M, KEY_L, KEY_W,
KEY_S,KEY_V, KEY_C, KEY_Z, KEY_POWER};
static struct hyn_ts_data *gesture_data = NULL;
/* sysfs gesture node
* read example: cat hyn_gesture_mode ---read gesture mode
* write example:echo 01 > hyn_gesture_mode ---write gesture mode to 01
*/
static ssize_t hyn_gesture_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
HYN_ENTER();
mutex_lock(&gesture_data->mutex_fs);
count = sprintf(buf, "Gesture Mode: %s\n", gesture_data->gesture_is_enable ? "On" : "Off");
count += sprintf(buf + count, "Reg = %d\n", gesture_data->gesture_id);
mutex_unlock(&gesture_data->mutex_fs);
return count;
}
static ssize_t hyn_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
HYN_ENTER();
mutex_lock(&gesture_data->mutex_fs);
if (buf[0]==1){
HYN_INFO("[GESTURE]enable gesture");
gesture_data->gesture_is_enable= ENABLE;
}else if (buf[0]==0){
HYN_INFO("[GESTURE]disable gesture");
gesture_data->gesture_is_enable = DISABLE;
}
mutex_unlock(&gesture_data->mutex_fs);
return count;
}
static DEVICE_ATTR (hyn_gesture_mode, S_IRUGO|S_IWUSR, hyn_gesture_show, hyn_gesture_store);
static struct attribute *hyn_gesture_mode_attrs[] =
{
&dev_attr_hyn_gesture_mode.attr,
NULL,
};
static struct attribute_group hyn_gesture_group =
{
.attrs = hyn_gesture_mode_attrs,
};
int hyn_gesture_init(struct hyn_ts_data *ts_data)
{
u8 i;
int ret = -1;
struct input_dev *dev = ts_data->input_dev;
HYN_ENTER();
gesture_data = ts_data;
for(i = 0; i< sizeof(gesture_key); i++){
input_set_capability(dev, EV_KEY, gesture_key[i]);
__set_bit(gesture_key[i], dev->keybit);
}
ts_data->gesture_id = 0xFF;
ts_data->gesture_is_enable = ENABLE;
ret = sysfs_create_group(&ts_data->dev->kobj, &hyn_gesture_group);
if(ret){
HYN_ERROR("ges_sys_node creat failed");
}
return ret;
}
void hyn_gesture_report(struct hyn_ts_data *ts_data)
{
struct input_dev *dev = ts_data->input_dev;//ges_input_dev;//ts_data->input_dev;
if(ts_data->gesture_id < sizeof(gesture_key)){
input_report_key(dev, gesture_key[ts_data->gesture_id], 1);
input_sync(dev);
input_report_key(dev, gesture_key[ts_data->gesture_id], 0);
input_sync(dev);
HYN_INFO("fw gesture idx:%d key value:%d",ts_data->gesture_id,gesture_key[ts_data->gesture_id]);
}
}
void hyn_gesture_exit(struct hyn_ts_data *ts_data)
{
sysfs_remove_group(&ts_data->dev->kobj, &hyn_gesture_group);
}

View File

@@ -0,0 +1,240 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_i2c.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#ifdef I2C_PORT
#if (I2C_USE_DMA==1)
int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len)
{
int ret = -1;
struct i2c_msg i2c_msg;
mutex_lock(&ts_data->mutex_bus);
i2c_msg.addr = ts_data->client->addr;
i2c_msg.flags = I2C_M_RD;
i2c_msg.len = len;
i2c_msg.buf = buf;
ret = i2c_transfer(ts_data->client->adapter, &i2c_msg, 1);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len)
{
int ret = 0;
struct i2c_msg i2c_msg;
u8 cmd_len = reg_len&0x0F;
if(cmd_len > 4) return -1;
mutex_lock(&ts_data->mutex_bus);
i2c_msg.addr = ts_data->client->addr;
i2c_msg.flags = 0;
i2c_msg.len = len;
i2c_msg.buf = buf;
ret = i2c_transfer(ts_data->client->adapter, &i2c_msg, 1);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen)
{
int ret = 0,i=0;
struct i2c_msg i2c_msg[2];
u8 wbuf[4];
u8 cmd_len = reg_len&0x0F;
if(cmd_len==0 || cmd_len > 4) return -1;
mutex_lock(&ts_data->mutex_bus);
memset(wbuf,0,sizeof(wbuf));
i = cmd_len;
while(i){
i--;
wbuf[i] = reg_addr;
reg_addr >>= 8;
}
i2c_msg[0].addr = ts_data->client->addr;
i2c_msg[0].flags = 0;
i2c_msg[0].len = cmd_len;
i2c_msg[0].buf = wbuf;
ret = i2c_transfer(ts_data->client->adapter, &i2c_msg[0], 1);
if(rlen){
i2c_msg[1].addr = ts_data->client->addr;
i2c_msg[1].flags = I2C_M_RD;
i2c_msg[1].buf = rbuf;
i2c_msg[1].len = rlen;
ret |= i2c_transfer(ts_data->client->adapter, &i2c_msg[1], 1);
}
// ret = i2c_transfer(ts_data->client->adapter, i2c_msg, rlen ? 2:1);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
#elif (I2C_USE_DMA==2)
int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len)
{
int ret = 0;
mutex_lock(&ts_data->mutex_bus);
ts_data->client->addr = ((ts_data->client->addr & I2C_MASK_FLAG) | I2C_DMA_FLAG);
memcpy(ts_data->dma_buff_va,buf, len);
ret = i2c_master_send(ts_data->client, (u8 *)ts_data->dma_buff_pa, len);
ts_data->client->addr = ts_data->client->addr& I2C_MASK_FLAG & (~I2C_DMA_FLAG);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len)
{
int ret = 0;
mutex_lock(&ts_data->mutex_bus);
ts_data->client->addr = ((ts_data->client->addr & I2C_MASK_FLAG) | I2C_DMA_FLAG);
ret = i2c_master_recv(ts_data->client, (u8 *)ts_data->dma_buff_pa, len);
memcpy(buf, ts_data->dma_buff_va, len);
ts_data->client->addr = ts_data->client->addr& I2C_MASK_FLAG & (~I2C_DMA_FLAG);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen)
{
int ret = 0,i=0;
u8 wbuf[4];
mutex_lock(&ts_data->mutex_bus);
reg_len = reg_len&0x0F;
memset(wbuf,0,sizeof(wbuf));
i = reg_len;
while(i){
i--;
wbuf[i] = reg_addr;
reg_addr >>= 8;
}
ts_data->client->addr = ((ts_data->client->addr & I2C_MASK_FLAG) | I2C_DMA_FLAG);
memcpy(ts_data->dma_buff_va,wbuf, reg_len);
ret = i2c_master_send(ts_data->client, (u8 *)ts_data->dma_buff_pa, reg_len);
if(rlen){
ret |= i2c_master_recv(ts_data->client, (u8 *)ts_data->dma_buff_pa, rlen);
memcpy(rbuf, ts_data->dma_buff_va, rlen);
}
ts_data->client->addr = ts_data->client->addr& I2C_MASK_FLAG & (~I2C_DMA_FLAG);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
#else //0
int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len)
{
int ret = -1;
mutex_lock(&ts_data->mutex_bus);
while(len){
if(len > HYN_TRANSFER_LIMIT_LEN){
ret = i2c_master_recv(ts_data->client, buf, HYN_TRANSFER_LIMIT_LEN);
len -= HYN_TRANSFER_LIMIT_LEN;
buf += HYN_TRANSFER_LIMIT_LEN;
}
else{
ret = i2c_master_recv(ts_data->client, buf, len);
len = 0;
}
if (ret < 0) {
break;
}
}
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len)
{
int ret = 0;
u8 cmd_len = reg_len&0x0F;
if(cmd_len > 4) return -1;
mutex_lock(&ts_data->mutex_bus);
#if HYN_TRANSFER_LIMIT_LEN < 1048
if(len > HYN_TRANSFER_LIMIT_LEN){
u32 reg = U8TO32(buf[0],buf[1],buf[2],buf[3])>>((4-cmd_len)*8);
u8 w_buf[HYN_TRANSFER_LIMIT_LEN],i;
u16 step = HYN_TRANSFER_LIMIT_LEN-cmd_len;
u16 w_len = 0;
buf += cmd_len;
len -= cmd_len;
while(len){
i = cmd_len;
while(i--){
w_buf[cmd_len-1-i] = reg>>(i*8);
}
memcpy(&w_buf[cmd_len],buf,step);
if(0==(reg_len&0x80)){
reg += step;
}
else{
reg = (reg&0xffff0000)|((reg>>8)&0xff)|((reg<<8)&0xff00);
reg += step;
reg = (reg&0xffff0000)|((reg>>8)&0xff)|((reg<<8)&0xff00);
}
buf += step;
if(len > step){
w_len = HYN_TRANSFER_LIMIT_LEN;
len -= step;
}
else{
w_len = len+cmd_len;
len = 0;
}
ret = i2c_master_send(ts_data->client, w_buf, w_len);
if(ret < 0) break;
}
}else
#endif
{
ret = i2c_master_send(ts_data->client, buf, len);
}
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen)
{
int ret = 0,i=0;
u8 wbuf[4];
u8 cmd_len = reg_len&0x0F;
if(cmd_len==0 || cmd_len > 4) return -1;
mutex_lock(&ts_data->mutex_bus);
do{
i = cmd_len-1;
do{
wbuf[cmd_len-1-i] = reg_addr>>(i*8);
}while(i--);
ret = i2c_master_send(ts_data->client, wbuf, cmd_len);
if(rlen){
ret |= i2c_master_recv(ts_data->client, rbuf, rlen < HYN_TRANSFER_LIMIT_LEN ? rlen : HYN_TRANSFER_LIMIT_LEN);
}
if(ret < 0 || rlen <= HYN_TRANSFER_LIMIT_LEN) break;
rbuf += HYN_TRANSFER_LIMIT_LEN;
rlen -= HYN_TRANSFER_LIMIT_LEN;
if(0==(reg_len&0x80)){
reg_addr += HYN_TRANSFER_LIMIT_LEN;
}
else{
reg_addr = (reg_addr&0xffff0000)|((reg_addr>>8)&0xff)|((reg_addr<<8)&0xff00);
reg_addr += HYN_TRANSFER_LIMIT_LEN;
reg_addr = (reg_addr&0xffff0000)|((reg_addr>>8)&0xff)|((reg_addr<<8)&0xff00);
}
}while(1);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? -1:0;
}
#endif
#endif

View File

@@ -0,0 +1,394 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_prox.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
static struct hyn_ts_data *hyn_prox_data = NULL;
static const struct hyn_ts_fuc* hyn_prox_fun = NULL;
#if (HYN_PROX_TYEP==4) //Spread
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>
#define CTP_IOCTL_MAGIC 0x13
#define CTP_IOCTL_PROX_ON _IOW(CTP_IOCTL_MAGIC, 1, int)
#define CTP_IOCTL_PROX_OFF _IOW(CTP_IOCTL_MAGIC, 2, int)
#define CTP_PROXIMITY_DEVICE_NAME "ltr_558als" //match HAL name
static long hyn_ioctl_operate(struct file *file, unsigned int cmd, unsigned long arg)
{
HYN_INFO("prox_ioctl_operate %d!\n", cmd);
switch(cmd)
{
case CTP_IOCTL_PROX_ON:
hyn_prox_fun->tp_prox_handle(1);
break;
case CTP_IOCTL_PROX_OFF:
hyn_prox_fun->tp_prox_handle(0);
break;
default:
HYN_ERROR("%s: invalid cmd %d\n", __func__, _IOC_NR(cmd));
return -EINVAL;
}
return 0;
}
static struct file_operations hyn_proximity_fops = {
.owner = THIS_MODULE,
.open = NULL,
.release = NULL,
.unlocked_ioctl = hyn_ioctl_operate
};
struct miscdevice hyn_proximity_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = CTP_PROXIMITY_DEVICE_NAME, //match the hal's name
.fops = &hyn_proximity_fops,
.mode = 0x666,
};
int hyn_proximity_int(struct hyn_ts_data *ts_data)
{
HYN_ENTER();
int ret;
hyn_prox_data = ts_data;
hyn_prox_fun = ts_data->hyn_fuc_used;
hyn_prox_data->prox_is_enable = 0;
ret = misc_register(&hyn_proximity_misc);
if (ret < 0){
HYN_ERROR("%s: could not register misc device\n", __func__);
goto misc_device_failed;
}
input_set_abs_params(hyn_prox_data->input_dev, ABS_DISTANCE, 0, 1, 0, 0);
return 0;
misc_device_failed:
return ret;
}
int hyn_proximity_report(u8 proximity_value)
{
HYN_ENTER();
input_report_abs(hyn_prox_data->input_dev, ABS_DISTANCE, proximity_value);
input_mt_sync(hyn_prox_data->input_dev);
input_sync(hyn_prox_data->input_dev);
return 0;
}
int hyn_proximity_exit(void)
{
HYN_ENTER();
misc_deregister(&hyn_proximity_misc);
return 0;
}
#elif (HYN_PROX_TYEP==3) //alps sensor
#include <hwmsensor.h>
//#include <hwmsen_dev.h>
#include <sensors_io.h>
#include <alsps.h>
static int ps_open_report_data(int open)
{
/* should queue work to report event if is_report_input_direct=true */
return 0;
}
/* if use this type of enable , Psensor only enabled but not report inputEvent to HAL */
static int ps_enable_nodata(int en)
{
int ret = 0;
HYN_INFO("[PROXIMITY]SENSOR_ENABLE value = %d", en);
/* Enable proximity */
ret = hyn_prox_fun->tp_prox_handle(en);
return ret;
}
static int ps_set_delay(u64 ns)
{
return 0;
}
static int ps_flush(void)
{
return ps_flush_report();
}
static int ps_batch(int flag, int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs)
{
int value = 0;
value = (int)samplingPeriodNs / 1000 / 1000;
return 0;
}
static int ps_get_data(int *value, int *status)
{
*value = (int)hyn_prox_data->prox_state;
HYN_INFO("fts_proximity_data.detect = %d\n", *value);
*status = SENSOR_STATUS_ACCURACY_MEDIUM;
return 0;
}
static int ps_calibration(int type, int value)
{
return 0;
}
static int ps_threshold_setting(int type, int value[2])
{
return 0;
}
int ps_local_init(void)
{
int err = 0;
struct ps_control_path ps_ctl = { 0 };
struct ps_data_path ps_data = { 0 };
HYN_ENTER();
ps_ctl.is_use_common_factory = false;
ps_ctl.open_report_data = ps_open_report_data;
ps_ctl.enable_nodata = ps_enable_nodata;
ps_ctl.batch = ps_batch;
ps_ctl.flush = ps_flush;
ps_ctl.set_delay = ps_set_delay;
ps_ctl.ps_calibration = ps_calibration;
ps_ctl.ps_threshold_setting = ps_threshold_setting;
ps_ctl.is_report_input_direct = true;
ps_ctl.is_support_batch = false;
err = ps_register_control_path(&ps_ctl);
HYN_INFO("psregister control_path %s = %d\n",err? "fail":"success", err);
ps_data.get_data = ps_get_data;
ps_data.vender_div = 100;
err = ps_register_data_path(&ps_data);
HYN_INFO("psregister data_path %s = %d\n",err? "fail":"success", err);
return err;
}
int ps_local_uninit(void)
{
return 0;
}
struct alsps_init_info ps_init_info = {
.name = "hyn_ts",
.init = ps_local_init,
.uninit = ps_local_uninit,
};
int hyn_proximity_int(struct hyn_ts_data *ts_data)
{
int ret = 0;
HYN_ENTER();
hyn_prox_data = ts_data;
hyn_prox_fun = ts_data->hyn_fuc_used;
hyn_prox_data->prox_is_enable = 0;
hyn_prox_data->prox_state = PS_FAR_AWAY;
alsps_driver_add(&ps_init_info);
// ps_local_init();
HYN_INFO("hyn_proximity_int exit");
return ret;
}
int hyn_proximity_report(u8 proximity_value)
{
int ret;
ret = ps_report_interrupt_data(proximity_value);
return ret;
}
int hyn_proximity_exit(void)
{
HYN_ENTER();
return 0;
}
#elif (HYN_PROX_TYEP==2)//mtk sensor
#include <hwmsensor.h>
#include <hwmsen_dev.h>
#include <sensors_io.h>
#define SENSOR_DELAY 0
#define SENSOR_ENABLE 0
#define SENSOR_GET_DATA 0
#define SENSOR_STATUS_ACCURACY_MEDIUM 0
struct hwmsen_object obj_ps;
static int hyn_proximiy_operate(void* self, uint32_t command, void* buff_in, int size_in,
void* buff_out, int size_out, int* actualout)
{
int err = 0,value;
HYN_INFO("prox command = 0x%02X\n", command);
switch (command)
{
case SENSOR_DELAY:
if((buff_in == NULL) || (size_in < sizeof(int))){
HYN_ERROR("Set delay parameter error!\n");
err = -EINVAL;
}
// Do nothing
break;
case SENSOR_ENABLE:
if((buff_in == NULL) || (size_in < sizeof(int))){
HYN_ERROR("Enable sensor parameter error!\n");
err = -EINVAL;
}else{
value = *(int *)buff_in;
hyn_prox_fun->tp_prox_handle(value > 0 ? 1 : 0);
}
break;
case SENSOR_GET_DATA:
if((buff_out == NULL)){
HYN_ERROR("get sensor data parameter error!\n");
err = -EINVAL;
}else{
hyn_proximity_report(hyn_prox_data->prox_state);
}
break;
default:
HYN_ERROR("proxmy sensor operate function no this parameter %d!\n", command);
err = -1;
break;
}
return err;
}
int hyn_proximity_int(struct hyn_ts_data *ts_data)
{
HYN_ENTER();
int ret;
hyn_prox_data = ts_data;
hyn_prox_fun = ts_data->hyn_fuc_used;
hyn_prox_data->prox_is_enable = 0;
obj_ps.polling = 0;//interrupt mode
obj_ps.sensor_operate = hyn_proximiy_operate;
ret = hwmsen_attach(ID_PROXIMITY, &obj_ps);
return ret;
}
int hyn_proximity_report(u8 proximity_value)
{
HYN_ENTER();
int ret=0;
struct hwm_sensor_data sensor_data;
sensor_data.values[0] = proximity_value;
sensor_data.value_divide = 1;
sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;
ret = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data);
if (ret){
HYN_ERROR(" proxi call hwmsen_get_interrupt_data failed= %d\n", err);
}
return ret;
}
int hyn_proximity_exit(void)
{
HYN_ENTER();
return 0;
}
#elif (HYN_PROX_TYEP==1)//default sensor
static ssize_t hyn_prox_show(struct device *dev,struct device_attribute *attr, char *buf)
{
return sprintf(buf, "proximity is %s value:%d\n",hyn_prox_data->prox_is_enable ? "enable":"disable" ,hyn_prox_data->prox_state);
}
/* Allow users to enable/disable prox */
static ssize_t hyn_prox_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
{
unsigned long enable;
enable = simple_strtoul(buf, NULL, 10);
hyn_prox_fun->tp_prox_handle(enable > 0 ? 1 : 0);
return count;
}
static DEVICE_ATTR (hyn_prox_enable, S_IRUGO|S_IWUSR, hyn_prox_show, hyn_prox_store);
static struct attribute *hyn_prox_enable_attrs[] =
{
&dev_attr_hyn_prox_enable.attr,
NULL,
};
static struct attribute_group hyn_prox_group =
{
.attrs = hyn_prox_enable_attrs,
};
int hyn_proximity_int(struct hyn_ts_data *ts_data)
{
HYN_ENTER();
int ret;
hyn_prox_data = ts_data;
hyn_prox_fun = ts_data->hyn_fuc_used;
hyn_prox_data->prox_is_enable = 0;
__set_bit(KEY_SLEEP, hyn_prox_data->input_dev->evbit);
__set_bit(KEY_WAKEUP, hyn_prox_data->input_dev->evbit);
ret = sysfs_create_group(&ts_data->dev->kobj, &hyn_prox_group);
if(ret){
HYN_ERROR("prox_sys_node creat failed");
}
return ret;
}
int hyn_proximity_report(u8 proximity_value)
{
HYN_ENTER();
int keycode = proximity_value ? KEY_SLEEP:KEY_WAKEUP;
input_report_key(hyn_prox_data->input_dev, keycode, 1);
input_sync(hyn_prox_data->input_dev);
input_report_key(hyn_prox_data->input_dev, keycode, 0);
input_sync(hyn_prox_data->input_dev);
return 0;
}
int hyn_proximity_exit(void)
{
HYN_ENTER();
sysfs_remove_group(&hyn_prox_data->dev->kobj, &hyn_prox_group);
return 0;
}
#elif (HYN_PROX_TYEP==0)
int hyn_proximity_int(struct hyn_ts_data *ts_data)
{
HYN_ENTER();
hyn_prox_data = ts_data;
hyn_prox_fun = ts_data->hyn_fuc_used;
return 0;
}
int hyn_proximity_report(u8 proximity_value)
{
HYN_ENTER();
return 0;
}
int hyn_proximity_exit(void)
{
HYN_ENTER();
return 0;
}
#endif

View File

@@ -0,0 +1,100 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_spi.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#ifndef I2C_PORT
int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len)
{
struct spi_message msg;
struct spi_transfer transfer[1] = { {0} };
int ret;
mutex_lock(&ts_data->mutex_bus);
spi_message_init(&msg);
transfer[0].len = len;
transfer[0].delay_usecs = SPI_DELAY_CS;
transfer[0].tx_buf = buf;
transfer[0].rx_buf = NULL;
spi_message_add_tail(&transfer[0], &msg);
ret = spi_sync(ts_data->client, &msg);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? ret:0;
}
int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len)
{
struct spi_message msg;
struct spi_transfer transfer[1] = { {0} };
int ret;
mutex_lock(&ts_data->mutex_bus);
spi_message_init(&msg);
transfer[0].len = len;
transfer[0].delay_usecs = SPI_DELAY_CS;
transfer[0].tx_buf = NULL;
transfer[0].rx_buf = buf;
spi_message_add_tail(&transfer[0], &msg);
ret = spi_sync(ts_data->client, &msg);
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? ret:0;
}
int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen)
{
int ret = 0,i=0;
struct spi_message msg;
struct spi_transfer transfer[2] = { {0}, {0} };
u8 cmd[4];
mutex_lock(&ts_data->mutex_bus);
reg_len = reg_len&0x0F;
memset(cmd,0,sizeof(cmd));
i = reg_len;
while(i){
i--;
cmd[i] = reg_addr;
reg_addr >>= 8;
}
spi_message_init(&msg);
transfer[0].len = reg_len;
transfer[0].tx_buf = cmd;
transfer[0].rx_buf = NULL;
spi_message_add_tail(&transfer[0], &msg);
ret = spi_sync(ts_data->client, &msg);
if (ret < 0) {
mutex_unlock(&ts_data->mutex_bus);
return ret;
}
udelay(20);
if (rlen > 0) {
spi_message_init(&msg);
transfer[1].len = rlen;
transfer[1].delay_usecs = SPI_DELAY_CS;
transfer[1].tx_buf = NULL;
transfer[1].rx_buf = rbuf;
spi_message_add_tail(&transfer[1], &msg);
ret = spi_sync(ts_data->client, &msg);
}
mutex_unlock(&ts_data->mutex_bus);
return ret < 0 ? ret:0;
}
#endif

View File

@@ -0,0 +1,352 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_tool.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
#if HYN_APK_DEBUG_EN
#define HYN_PROC_DIR_NAME "hyn_apk_tool"
#define HYN_PROC_NODE_NAME "fops_nod"
static struct hyn_ts_data *hyn_tool_data = NULL;
static const struct hyn_ts_fuc* hyn_tool_fun = NULL;
static struct proc_dir_entry *g_tool_dir = NULL;
static struct proc_dir_entry *g_tool_node = NULL;
static int misc_state = -1;
#define READ_TPINF (0x0A)
#define WRITE_IIC (0x1A) //len
#define READ_REG (0x2A)
#define READ_IIC (0x3A)
#define SET_WORK_MODE (0x7A)
#define RESET_IC (0xCA)
#define UPDATA_FW (0xAC)
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
static int hyn_proc_tool_read(char *user_buf, char **start, off_t off, int count, int *eof, void *f_pos)
{
unsigned char *buf = NULL;
int ret_len = 0,ret = 0,copy_len = 0;
int mt_total_len = hyn_tool_data->hw_info.fw_sensor_rxnum*hyn_tool_data->hw_info.fw_sensor_txnum*2
+ (hyn_tool_data->hw_info.fw_sensor_rxnum + hyn_tool_data->hw_info.fw_sensor_txnum)*2;
u8 *cmd = hyn_tool_data->host_cmd_save;
mutex_lock(&hyn_tool_data->mutex_fs);
if(*f_pos != 0){
goto tool_read_end;
}
ret_len = (mt_total_len + sizeof(struct ts_frame))*2;
// if(ret_len > count){
// ret_len = count;
// }
if(hyn_tool_data->work_mode == FAC_TEST_MODE){
ret_len += mt_total_len;
}
copy_len = ret_len > count ? count:ret_len;
buf = kzalloc(ret_len, GFP_KERNEL);
// buf = kzalloc(ret_len, GFP_KERNEL);
if(buf == NULL){
HYN_ERROR("zalloc GFP_KERNEL memory failed.\n");
goto tool_read_end;
}
if(DIFF_MODE <= hyn_tool_data->work_mode && FAC_TEST_MODE >= hyn_tool_data->work_mode){
wait_event_interruptible_timeout(hyn_tool_data->wait_irq,(atomic_read(&hyn_tool_data->hyn_irq_flg)==1),msecs_to_jiffies(500)); //
atomic_set(&hyn_tool_data->hyn_irq_flg,0);
if(hyn_tool_data->work_mode == FAC_TEST_MODE){
if(NULL != hyn_tool_fun->tp_get_test_result){
u8 restut[4];
if(buf == NULL){
HYN_ERROR("zalloc GFP_KERNEL memory failed.\n");
goto tool_read_end;
}
*(int*)&restut = hyn_tool_fun->tp_get_test_result(buf,ret_len);
HYN_INFO("test ret = %d",ret);
memcpy(user_buf,restut,4);
memcpy(user_buf+4,buf,copy_len-4);
}
}
else{
ret = hyn_tool_fun->tp_get_dbg_data(buf,ret_len);
if(ret > 0)
memcpy(user_buf,buf,copy_len);
}
}
else{
if(cmd[0] == READ_REG){ //0:head 1~4:reg 5:reg_len 6~7:read_len
u32 reg_addr = U8TO32(cmd[4],cmd[3],cmd[2],cmd[1]); //eg (read A1 A2 len 256):2A 00 00 A1 A2 02 FF 00
ret = hyn_wr_reg(hyn_tool_data,reg_addr,cmd[5],buf,copy_len);
memcpy(user_buf,buf,copy_len);
}
else if(cmd[0] == READ_IIC){ //0:head 1~2:read_len
ret = hyn_read_data(hyn_tool_data,buf,copy_len);
memcpy(user_buf,buf,copy_len);
}
else if(cmd[0] == READ_TPINF){
memcpy(user_buf,&hyn_tool_data->hw_info,sizeof(hyn_tool_data->hw_info));
}
else if(cmd[0] == UPDATA_FW){
ret_len = sizeof(hyn_tool_data->fw_updata_process);
memcpy(user_buf,&hyn_tool_data->fw_updata_process,copy_len);
msleep(1);
}
}
tool_read_end:
if(!IS_ERR_OR_NULL(buf)){
kfree(buf);
}
mutex_unlock(&hyn_tool_data->mutex_fs);
// HYN_INFO("count = %d copy len = %d ret = %d\r\n",(int)count,ret_len,ret);
return count;
}
#else
static int hyn_proc_tool_open(struct inode *pinode, struct file *pfile)
{
HYN_ENTER();
return 0;
}
static ssize_t hyn_proc_tool_read(struct file *page,char __user *user_buf, size_t count, loff_t *f_pos)
{
unsigned char *buf = NULL;
int ret_len = 0,ret = 0,copy_len = 0;
int mt_total_len = hyn_tool_data->hw_info.fw_sensor_rxnum*hyn_tool_data->hw_info.fw_sensor_txnum*2
+ (hyn_tool_data->hw_info.fw_sensor_rxnum + hyn_tool_data->hw_info.fw_sensor_txnum)*2;
u8 *cmd = hyn_tool_data->host_cmd_save;
mutex_lock(&hyn_tool_data->mutex_fs);
if(*f_pos != 0){
goto tool_read_end;
}
ret_len = (mt_total_len + sizeof(struct ts_frame))*2;
// if(ret_len > count){
// ret_len = count;
// }
if(hyn_tool_data->work_mode == FAC_TEST_MODE){
ret_len += mt_total_len;
}
copy_len = ret_len > count ? count:ret_len;
buf = kzalloc(ret_len, GFP_KERNEL);
// buf = kzalloc(ret_len, GFP_KERNEL);
if(buf == NULL){
HYN_ERROR("zalloc GFP_KERNEL memory failed.\n");
goto tool_read_end;
}
if(DIFF_MODE <= hyn_tool_data->work_mode && FAC_TEST_MODE >= hyn_tool_data->work_mode){
wait_event_interruptible_timeout(hyn_tool_data->wait_irq,(atomic_read(&hyn_tool_data->hyn_irq_flg)==1),msecs_to_jiffies(500)); //
atomic_set(&hyn_tool_data->hyn_irq_flg,0);
if(hyn_tool_data->work_mode == FAC_TEST_MODE){
if(NULL != hyn_tool_fun->tp_get_test_result){
u8 restut[4];
if(buf == NULL){
HYN_ERROR("zalloc GFP_KERNEL memory failed.\n");
goto tool_read_end;
}
*(int*)&restut = hyn_tool_fun->tp_get_test_result(buf,ret_len);
HYN_INFO("test ret = %d",ret);
ret = copy_to_user(user_buf,restut,4);
ret |= copy_to_user(user_buf+4,buf,copy_len-4);
if (ret)
HYN_INFO("FAC_TEST_MODE copy_to_user ret = %d",ret);
}
}
else{
ret = hyn_tool_fun->tp_get_dbg_data(buf,ret_len);
if(ret > 0) {
ret = copy_to_user(user_buf,buf,copy_len);
if (ret)
HYN_INFO("other work_mode copy_to_user ret = %d",ret);
}
}
}
else{
if(cmd[0] == READ_REG){ //0:head 1~4:reg 5:reg_len 6~7:read_len
u32 reg_addr = U8TO32(cmd[4],cmd[3],cmd[2],cmd[1]); //eg (read A1 A2 len 256):2A 00 00 A1 A2 02 FF 00
hyn_wr_reg(hyn_tool_data,reg_addr,cmd[5],buf,copy_len);
ret = copy_to_user(user_buf,buf,copy_len);
if (ret)
HYN_INFO("READ_REG copy_to_user ret = %d",ret);
}
else if(cmd[0] == READ_IIC){ //0:head 1~2:read_len
hyn_read_data(hyn_tool_data,buf,copy_len);
ret = copy_to_user(user_buf,buf,copy_len);
if (ret)
HYN_INFO("READ_IIC copy_to_user ret = %d",ret);
}
else if(cmd[0] == READ_TPINF){
ret = copy_to_user(user_buf,&hyn_tool_data->hw_info,sizeof(hyn_tool_data->hw_info));
if (ret)
HYN_INFO("READ_TPINF copy_to_user ret = %d",ret);
}
else if(cmd[0] == UPDATA_FW){
// ret_len = sizeof(hyn_tool_data->fw_updata_process);
ret = copy_to_user(user_buf,&hyn_tool_data->fw_updata_process,copy_len);
if (ret)
HYN_INFO("UPDATA_FW copy_to_user ret = %d",ret);
msleep(1);
}
}
tool_read_end:
if(!IS_ERR_OR_NULL(buf)){
kfree(buf);
}
mutex_unlock(&hyn_tool_data->mutex_fs);
// HYN_INFO("count = %d copy len = %d ret = %d\r\n",(int)count,ret_len,ret);
return count;
}
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
static int hyn_proc_tool_write(struct file *file, const char __user *buffer,size_t count, void *data)
#else
static ssize_t hyn_proc_tool_write(struct file *file, const char __user *buffer,size_t count, loff_t *data)
#endif
{
u8 *cmd = NULL;
int ret = 0;
HYN_ENTER();
mutex_lock(&hyn_tool_data->mutex_fs);
#define MAX_W_SIZE (1024+8)
if(count > MAX_W_SIZE){
ret = -1;
HYN_ERROR("count > MAX_W_SIZE\n");
goto ERRO_WEND;
}
cmd = kzalloc(count, GFP_KERNEL);
if(IS_ERR_OR_NULL(cmd)){
ret = -1;
HYN_ERROR("kzalloc failed\n");
goto ERRO_WEND;
}
if(copy_from_user(cmd, buffer, count)){
ret = -1;
HYN_ERROR("copy data from user space failed.\n");
goto ERRO_WEND;
}
memcpy(hyn_tool_data->host_cmd_save,cmd,count <sizeof(hyn_tool_data->host_cmd_save) ? count:sizeof(hyn_tool_data->host_cmd_save));
HYN_INFO("cmd:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x***len:%d ", cmd[0], cmd[1],cmd[2], cmd[3],cmd[4], cmd[5],cmd[6], cmd[7],(u16)count);
switch(cmd[0]){
case UPDATA_FW: // apk download bin
HYN_INFO("updata file_name =%s",&cmd[1]);
snprintf(hyn_tool_data->fw_file_name, sizeof(hyn_tool_data->fw_file_name), "%127.127s", &cmd[1]);
hyn_tool_data->fw_updata_process = 0;
if(0==queue_work(hyn_tool_data->hyn_workqueue,&hyn_tool_data->work_updata_fw)){
HYN_ERROR("queue_work work_updata_fw failed");
}
break;
case SET_WORK_MODE://
atomic_set(&hyn_tool_data->hyn_irq_flg,0);
ret = hyn_tool_fun->tp_set_workmode(cmd[1],0);
break;
case RESET_IC:
hyn_tool_fun->tp_rest();
break;
case WRITE_IIC: //
ret = hyn_write_data(hyn_tool_data,&cmd[1],2,count-1);
break;
default:
break;
}
ERRO_WEND:
if(!IS_ERR_OR_NULL(cmd)){
kfree(cmd);
}
mutex_unlock(&hyn_tool_data->mutex_fs);
return ret == 0 ? count:-1;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
static const struct file_operations proc_tool_fops = {
.owner = THIS_MODULE,
.open = hyn_proc_tool_open,
.read = hyn_proc_tool_read,
.write = hyn_proc_tool_write,
};
static struct miscdevice hyn_tool_dev = {
.fops = &proc_tool_fops,
.minor = MISC_DYNAMIC_MINOR,
.name = HYN_PROC_DIR_NAME,
.mode = S_IFREG|S_IRWXUGO,
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
static const struct proc_ops proc_tool_ops = { ////>=5.06
.proc_read = hyn_proc_tool_read,
.proc_write = hyn_proc_tool_write,
};
#endif
#endif
int hyn_tool_fs_int(struct hyn_ts_data *ts_data)
{
int ret = 0;
hyn_tool_data = ts_data;
hyn_tool_fun = ts_data->hyn_fuc_used;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
ret = misc_register(&hyn_tool_dev);
misc_state = ret;
HYN_INFO("hyn_tool_dev register %s",ret ? "failed":"success");
#endif
g_tool_dir = proc_mkdir(HYN_PROC_DIR_NAME, NULL);
if (IS_ERR_OR_NULL(g_tool_dir)){
HYN_INFO("proc_mkdir %s failed.\n",HYN_PROC_DIR_NAME);
return -1;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
g_tool_node = create_proc_entry(HYN_PROC_NODE_NAME, 0644, g_tool_dir);
g_tool_node->write_proc = hyn_proc_tool_write;
g_tool_node->read_proc = hyn_proc_tool_read;
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) //>=3.10
g_tool_node = proc_create(HYN_PROC_NODE_NAME, 0644|S_IFREG, g_tool_dir, &proc_tool_fops);
//proc_create_data(HYN_PROC_NODE_NAME, 0644 | S_IFREG, g_tool_dir, (void *)&proc_tool_fops, (void *)ts_data->client);
#else
g_tool_node = proc_create(HYN_PROC_NODE_NAME, 0644|S_IFREG, g_tool_dir, &proc_tool_ops);
#endif
if (IS_ERR_OR_NULL(g_tool_node)) {
HYN_INFO("proc_create %s failed.\n",HYN_PROC_NODE_NAME);
remove_proc_entry(HYN_PROC_DIR_NAME, NULL);
return -ENOMEM;
}
HYN_INFO("apk node creat success");
return 0;
}
void hyn_tool_fs_exit(void)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
if(!IS_ERR_OR_NULL(g_tool_dir)){
remove_proc_entry(HYN_PROC_DIR_NAME, NULL);
}
#else
if(!IS_ERR_OR_NULL(g_tool_dir)){
proc_remove(g_tool_dir);
}
if(0==misc_state){
misc_deregister(&hyn_tool_dev);
}
#endif
}
#endif

View File

@@ -0,0 +1,518 @@
/*
* drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_ts_ext.c
*
* hynitron TouchScreen driver.
*
* Copyright (c) 2025 hynitron
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "../hyn_core.h"
int hyn_power_source_ctrl(struct hyn_ts_data *ts_data, int enable)
{
int ret = 0;
HYN_ENTER();
if(IS_ERR_OR_NULL(ts_data) || IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)){
return ret;
}
if(ts_data->power_is_on != enable){
if(enable){
if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)){
ret |= regulator_enable(ts_data->plat_data.vdd_ana);
}
if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_i2c)){
ret |= regulator_enable(ts_data->plat_data.vdd_i2c);
}
}
else{
if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)){
ret |= regulator_disable(ts_data->plat_data.vdd_ana);
}
if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_i2c)){
ret |= regulator_disable(ts_data->plat_data.vdd_i2c);
}
}
ts_data->power_is_on = enable;
}
if(ret)
HYN_ERROR("set vdd %s regulator failed,ret=%d",enable ? "off":"on",ret);
return ret;
}
void hyn_irq_set(struct hyn_ts_data *ts_data, u8 value)
{
// HYN_ENTER();
if(atomic_read(&ts_data->irq_is_disable) != value){
if(value ==0){
disable_irq(ts_data->gpio_irq);
msleep(1); //wait switch
}
else{
enable_irq(ts_data->gpio_irq);
}
atomic_set(&ts_data->irq_is_disable,value);
// HYN_INFO("IRQ %d",value);
}
}
void hyn_set_i2c_addr(struct hyn_ts_data *ts_data,u8 addr)
{
#ifdef I2C_PORT
ts_data->client->addr = addr;
#endif
}
u16 hyn_sum16(int val, u8* buf,u16 len)
{
u16 sum = val;
while(len--) sum += *buf++;
return sum;
}
u32 hyn_sum32(int val, u32* buf,u16 len)
{
u32 sum = val;
while(len--) sum += *buf++;
return sum;
}
void hyn_esdcheck_switch(struct hyn_ts_data *ts_data, u8 enable)
{
#if ESD_CHECK_EN
if(IS_ERR_OR_NULL(ts_data->hyn_workqueue) || IS_ERR_OR_NULL(&ts_data->esdcheck_work)) return;
if(enable){
ts_data->esd_fail_cnt = 0;
queue_delayed_work(ts_data->hyn_workqueue, &ts_data->esdcheck_work,
msecs_to_jiffies(1000));
}
else{
cancel_delayed_work_sync(&ts_data->esdcheck_work);
}
#endif
}
int hyn_copy_for_updata(struct hyn_ts_data *ts_data,u8 *buf,u32 offset,u16 len)
{
int ret = -1;
#if (HYN_GKI_VER==0)
struct file *fp;
loff_t pos;
u8 *pdata;
// HYN_ENTER();
if(strlen(ts_data->fw_file_name) == 0)
return ret;
fp = filp_open(ts_data->fw_file_name,O_RDONLY, 0);//
if (IS_ERR(fp)) {
HYN_INFO("open file %s failed \r\n", ts_data->fw_file_name);
return -EIO;
}
// fp->f_op->llseek(fp, offset, 0);
fp->f_op->llseek(fp, 0, 0);
pdata = kzalloc(len, GFP_KERNEL);
if(IS_ERR_OR_NULL(pdata)){
HYN_ERROR("kzalloc failed");
filp_close(fp, NULL);
return -1;
}
pos = offset;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0)
{
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret=vfs_read(fp, pdata, len, &pos);
set_fs(old_fs);
}
#else
ret = hyn_fs_read(fp,pdata, len,&pos);
#endif
filp_close(fp, NULL);
// HYN_INFO("rlen = %d nlen = %d",ret,len);
if(ret <= len){
memcpy(buf,pdata,len);
ret = 0;
}
else{
ret = -3;
}
kfree(pdata);
#endif
return ret;
}
int hyn_wait_irq_timeout(struct hyn_ts_data *ts_data,int msec)
{
atomic_set(&ts_data->hyn_irq_flg,0);
while(msec--){
msleep(1);
if(atomic_read(&ts_data->hyn_irq_flg)==1){
atomic_set(&ts_data->hyn_irq_flg,0);
msec = -1;
break;
}
}
return msec == -1 ? 0:-1;
}
#define MAX_WROD_LEN (64)
int hyn_get_word(u8**sc_str, u8* ds_str)
{
u8 ch,cnt = 0,nul_flg = 0;
while(1){
ch = **sc_str;
*sc_str += 1;
if((ch==' '&& nul_flg) || ch=='\t' || ch=='\0' || (ch=='\r' && **sc_str == '\n') || ch=='\n'|| ch==','|| ch=='=' || cnt>=MAX_WROD_LEN){
*ds_str++ = '\0';
break;
}
if(ch >= 'A' && ch <= 'Z') ch = ch + 'a' - 'A';
if(ch!=' '){
*ds_str++ = ch;
nul_flg = 1;
}
cnt++;
}
return cnt;
}
int hyn_str_2_num(char *str,u8 type)
{
int ret = 0,step = 0,flg = 0,cnt = 15;
char ch;
while(*str != '\0' && --cnt){
ch = *str++;
if(ch==' ') continue;
else if(ch=='-' && step==0){
flg = 1;
continue;
}
if(type == 10){
if(ch <= '9' && ch >= '0'){
step++;
ret *= 10;
ret += (ch - '0');
}
else{
cnt = 0;
break;
}
}
else{
if(ch <= '9' && ch >= '0'){
step++;
ret *= 16;
ret += (ch - '0');
}
else if(ch <= 'f' && ch >= 'a'){
step++;
ret *= 16;
ret += (10 + ch - 'a');
}
else{
cnt = 0;
break;
}
}
}
// if(cnt == 0 || step==0)HYN_ERROR("failed");
return (cnt == 0 || step==0) ? 0xAC5AC5AC : (flg ? -ret:ret);
}
static int hyn_get_threshold(char *filename,char *match_string,s16 *pstore, u16 len)
{
int ret = 0;
HYN_ENTER();
#if (HYN_GKI_VER==0)
{
u8 *buf = NULL,*ptr = NULL;
u8 tmp_word[66];
u16 i;
int dec,cnt;
off_t fsize;
struct file *fp;
loff_t pos;
if(strlen(filename) == 0)
return ret;
fp = filp_open(filename, O_RDONLY, 0);
if (IS_ERR(fp)) {
HYN_INFO("error occurred while opening file %s.\n", filename);
return -EIO;
}
fp->f_op->llseek(fp, 0, 0);
fsize = fp->f_inode->i_size;
buf = vmalloc(fsize);
if(IS_ERR_OR_NULL(buf)){
HYN_ERROR("vmalloc failed");
filp_close(fp, NULL);
return -1;
}
pos = 0;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0)
{mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret=vfs_read(fp,buf, fsize, &pos);
set_fs(old_fs);}
#else
ret = hyn_fs_read(fp,buf,fsize,&pos);
#endif
HYN_INFO("read %s %s.ret:%d.\n",filename,ret==fsize ? "success":"failed",ret);
filp_close(fp, NULL);
////read finsh start match key string
i = fsize;
ptr = buf;
while(--i){
if(*ptr++ == '\n'){
cnt = strlen(match_string);
while(--cnt){
if(ptr[cnt]!= match_string[cnt]){
break;
}
}
if(cnt == 0 && ptr[0]== match_string[0]){
// HYN_INFO("match %s",match_string);
break; //ignor idx 0,1
}
}
}
if(i == 0){
ret = -1;
goto MATCH_FAIL1;
}
///////match key string end
i = 0;
while(i<10){
cnt = hyn_get_word(&ptr,tmp_word);
if(cnt==0){
i++;
continue;
}
// HYN_INFO("@@%s",tmp_word);
dec = hyn_str_2_num(tmp_word,10);
if(dec == 0xAC5AC5AC) continue;
*pstore = dec;
pstore++;
i = 0;
if(--len == 0) break;
}
ret = len ? -1:0;
MATCH_FAIL1:
if(!IS_ERR_OR_NULL(buf)) vfree(buf);
}
#endif
return ret;
}
int hyn_factory_multitest(struct hyn_ts_data *ts_data ,char *cfg_path, u8 *data,s16 *test_th,u8 test_item)
{
int ret = 0;
struct tp_info *ic = &ts_data->hw_info;
u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum,i=0;
u16 st_len = ic->fw_sensor_txnum + ic->fw_sensor_rxnum;
s16 *raw_h,*raw_l,*raw_s,*scap_p,tmp=0;
raw_h = (s16*)data;
raw_l = raw_h + mt_len;
raw_s = raw_l + mt_len;
scap_p = raw_s + st_len;
if(test_item & MULTI_OPEN_TEST){
//judge low TH
HYN_INFO("check MULTI_OPEN_TEST OpenMin");
if(hyn_get_threshold(cfg_path,"TX0OpenMin",test_th,mt_len)){
HYN_ERROR("read threshold failed");
return FAC_GET_CFG_FAIL;
}
for(i = mt_len; i< mt_len; i++){
if(*(raw_h+i)-*(raw_l+i) < test_th[i]) break;
}
if(i == mt_len){
HYN_INFO("open low pass");
}
else{
HYN_ERROR("open low test failed row= %d clo= %d %d<(th)%d"
,i/ic->fw_sensor_rxnum,i%ic->fw_sensor_rxnum,*(raw_h+i)-*(raw_l+i),test_th[i]);
return FAC_TEST_OPENL_FAIL;
}
//judge high TH
HYN_INFO("check MULTI_OPEN_TEST OpenMax");
if(hyn_get_threshold(cfg_path,"TX0OpenMax",test_th,mt_len)){
HYN_ERROR("read threshold failed");
return FAC_GET_CFG_FAIL;
}
for(i = 0; i< mt_len; i++){
if(*(raw_h+i)-*(raw_l+i) > test_th[i]) break;
}
if(i == mt_len){
HYN_INFO("open high pass");
}
else{
HYN_ERROR("open high test failed row= %d clo= %d %d>(th)%d"
,i/ic->fw_sensor_rxnum,i%ic->fw_sensor_rxnum,*(raw_h+i)-*(raw_l+i),test_th[i]);
return FAC_TEST_OPENH_FAIL;
}
}
if(test_item & MULTI_SHORT_TEST){
//judge short TH
if(hyn_get_threshold(cfg_path,"FactoryTxShortTh",&tmp,1)){
HYN_ERROR("read threshold failed");
return FAC_GET_CFG_FAIL;
}
for(i = 0; i< st_len; i++){
if(*(raw_s+i) < tmp) break;
}
HYN_INFO("%s,shortth = %d",i == st_len ? "short test pass":"short test failed",tmp);
if(i != st_len){
return FAC_TEST_SHORT_FAIL;
}
}
if(test_item & MULTI_SCAP_TEST){
// self captest
ret = hyn_get_threshold(cfg_path,"RxSCapScanMin",test_th,ic->fw_sensor_rxnum);
ret |= hyn_get_threshold(cfg_path,"TxSCapScanMin",test_th+ic->fw_sensor_rxnum,ic->fw_sensor_txnum);
ret |= hyn_get_threshold(cfg_path,"RxSCapScanMax",test_th+st_len,ic->fw_sensor_rxnum);
ret |= hyn_get_threshold(cfg_path,"TxSCapScanMax",test_th+st_len+ic->fw_sensor_rxnum,ic->fw_sensor_txnum);
if(ret){
HYN_ERROR("read threshold failed");
return FAC_GET_CFG_FAIL;
}
else{
// scap_fix = 128*(test_th[st_len+2] - test_th[2])/(abs(*(scap_p+2))+1);
for(i = 0; i< st_len; i++){
tmp = *(scap_p+i);//*scap_fix/128;
if(tmp < test_th[i] || tmp > test_th[st_len+i]) break;
}
if(i == st_len){
HYN_INFO("scap test pass");
}
else{
HYN_ERROR("scap test failed[%d] %d<%d>%d",i,test_th[i],tmp,test_th[st_len+i]);
return FAC_TEST_SCAP_FAIL;
}
}
}
return 0;
}
#if (HYN_GKI_VER==0)
static int arry_to_string(s16 *from,u16 cnt,u8 *des,u16 maxlen)
{
int str_cnt = 0;
int ret;
while(cnt--){
ret = snprintf(&des[str_cnt],maxlen, "%d,",*from++);
str_cnt += ret;
if(str_cnt > maxlen-ret){
str_cnt = maxlen;
HYN_ERROR("str full");
break;
}
}
return str_cnt;
}
#endif
int hyn_fac_test_log_save(char *log_name,struct hyn_ts_data *ts_data,s16 *test_data, int test_ret, u8 test_item)
{
HYN_ENTER();
#if (HYN_GKI_VER==0)
{
struct file *fp;
u8 w_buf[256],i;
int ret = -1;
if(strlen(log_name) == 0)
return ret;
fp = filp_open(log_name, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
HYN_INFO("error occurred while opening file %s.\n", log_name);
return -EIO;
}
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0)
{mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
#undef hyn_fs_write
#define hyn_fs_write vfs_write
#endif
ret = snprintf(w_buf,sizeof(w_buf), test_ret ==0 ? "factory test pass\n":"factory test ng\n");
hyn_fs_write(fp, w_buf, min_t(size_t, ret, sizeof(w_buf)-1), &fp->f_pos);
if(test_ret == FAC_GET_DATA_FAIL){
ret = snprintf(w_buf,sizeof(w_buf), "read fac_test data fail\n");
hyn_fs_write(fp, w_buf, ret, &fp->f_pos);
}
else{
if(test_item & MULTI_OPEN_TEST){
ret = snprintf(w_buf,sizeof(w_buf), "open high test data\n");
hyn_fs_write(fp, w_buf, ret, &fp->f_pos);
for(i = 0; i< ts_data->hw_info.fw_sensor_txnum; i++){
ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2);
w_buf[ret+1] = '\n';
hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos);
test_data += ts_data->hw_info.fw_sensor_rxnum;
}
ret = snprintf(w_buf,sizeof(w_buf), "open low test data\n");
hyn_fs_write(fp, w_buf, ret, &fp->f_pos);
for(i = 0; i< ts_data->hw_info.fw_sensor_txnum; i++){
ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2);
w_buf[ret+1] = '\n';
hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos);
test_data += ts_data->hw_info.fw_sensor_rxnum;
}
}
if(test_item & MULTI_SHORT_TEST){
ret = snprintf(w_buf,sizeof(w_buf), "short test data\n");
hyn_fs_write(fp, w_buf, ret, &fp->f_pos);
ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2);
w_buf[ret+1] = '\n';
hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos);
test_data += ts_data->hw_info.fw_sensor_rxnum;
ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_txnum,w_buf,sizeof(w_buf)-2);
w_buf[ret+1] = '\n';
hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos);
test_data += ts_data->hw_info.fw_sensor_txnum;
}
if(test_item & MULTI_SCAP_TEST){
ret = snprintf(w_buf,sizeof(w_buf), "scap test data\n");
hyn_fs_write(fp, w_buf, ret, &fp->f_pos);
ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2);
w_buf[ret+1] = '\n';
hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos);
test_data += ts_data->hw_info.fw_sensor_rxnum;
ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_txnum,w_buf,sizeof(w_buf)-2);
w_buf[ret+1] = '\n';
hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos);
// test_data += ts_data->hw_info.fw_sensor_txnum;
}
}
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0)
set_fs(old_fs);}
#endif
filp_close(fp, NULL);
}
#endif
return 0;
}

View File

@@ -0,0 +1,199 @@
1、芯片对应关系
----------匹配符-------------------------函数接口----------支持的芯片型号--------------
{.compatible = "hyn,66xx", .data = &hyn_cst66xx_fuc,}, /*support 36xx、35xx、66xx、68xx */
{.compatible = "hyn,36xxes", .data = &hyn_cst36xxes_fuc,}, /*support 154es 3654es 3640es*/
{.compatible = "hyn,3240", .data = &hyn_cst3240_fuc,}, /*support 3240 */
{.compatible = "hyn,92xx", .data = &hyn_cst92xx_fuc,}, /*support 9217、9220 */
{.compatible = "hyn,3xx", .data = &hyn_cst3xx_fuc,}, /*support 340、348、328、128、140、148*/
{.compatible = "hyn,7xx", .data = &hyn_cst7xx_fuc,}, /*support 726、826、836u*/
{.compatible = "hyn,8xxt", .data = &hyn_cst8xxT_fuc,}, /*support 816t、816d、820、08C*/
{.compatible = "hyn,226se", .data = &hyn_cst226se_fuc,}, /*support 226se 8922*/
2、I2c接口最小dts参考配置下面都是必配项
hynitron@5A {
compatible = "hyn,66xx"; //根据芯片型号配置
reg = <0x5A>; //根据芯片型号配置
interrupt-parent = <&tlmm>; //根据平台配置
interrupts = <65 0x02>; //根据平台配置
reset-gpio = <&tlmm 64 0x01>; //根据平台配置
irq-gpio = <&tlmm 65 0x02>; //根据平台配置
//panel = <&dsi_1080p_video>; //CONFIG_DRM_PANEL 需要配置
max-touch-number = <5>;
display-coords = <0 0 800 1280>;
pos-swap = <0>; //xy坐标交换
posx-reverse = <0>; //x坐标反向
posy-reverse = <0>; //y坐标反向
};
3、SPI接口最小dts参考配置下面都是必配项
spi@78b900{
hynitron@0 {
compatible = "hyn,66xx"; //根据芯片型号配置
reg = <0>; //根据芯片型号配置
spi-max-frequency=<6000000>; //默认配6M
interrupt-parent = <&tlmm>; //根据平台配置
interrupts = <65 0x02>; //根据平台配置
reset-gpio = <&tlmm 64 0x01>; //根据平台配置
irq-gpio = <&tlmm 65 0x02>; //根据平台配置
max-touch-number = <5>;
display-coords = <0 0 800 1280>;
pos-swap = <0>; //xy坐标交换
posx-reverse = <0>; //x坐标反向
posy-reverse = <0>; //y坐标反向
};
};
4、全dts参考配置:
hynitron@5A {
compatible = "hyn,66xx";
reg = <0x5A>;
vdd_ana-supply = <&pm8953_l10>;
vcc_i2c-supply = <&pm8953_l6>;
interrupt-parent = <&tlmm>;
interrupts = <65 0x02>;
reset-gpio = <&tlmm 64 0x01>;
irq-gpio = <&tlmm 65 0x02>;
pinctrl-names = "ts_active","ts_suspend";
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
max-touch-number = <5>;
display-coords = <0 0 800 1280>;
pos-swap = <1>;
posx-reverse = <0>;
posy-reverse = <0>;
key-number = <0>;
keys = <139 102 158>;
key-y-coord = <2000>;
key-x-coords = <200 600 800>;
};
PINCTL配置
pmx_ts_int_active {
ts_int_active: ts_int_active {
mux {
pins = "gpio65";
function = "gpio";
};
config {
pins = "gpio65";
drive-strength = <8>;
bias-pull-up;
};
};
};
pmx_ts_reset_active {
ts_reset_active: ts_reset_active {
mux {
pins = "gpio64";
function = "gpio";
};
config {
pins = "gpio64";
drive-strength = <8>;
bias-pull-up;
};
};
};
pmx_ts_int_suspend {
ts_int_suspend: ts_int_suspend {
mux {
pins = "gpio65";
function = "gpio";
};
config {
pins = "gpio65";
drive-strength = <2>;
bias-pull-down;
};
};
};
pmx_ts_reset_suspend {
ts_reset_suspend: ts_reset_suspend {
mux {
pins = "gpio64";
function = "gpio";
};
config {
pins = "gpio64";
drive-strength = <2>;
bias-pull-down;
};
};
};
3、参考Makefile配置:
obj-y += hynitron_touch.o
hynitron_touch-objs += hyn_core.o hyn_lib/hyn_i2c.o hyn_lib/hyn_spi.o hyn_lib/hyn_ts_ext.o hyn_lib/hyn_fs_node.o
hynitron_touch-objs += hyn_lib/hyn_tool.o
hynitron_touch-objs += hyn_lib/hyn_gesture.o
hynitron_touch-objs += hyn_lib/hyn_prox.o
hynitron_touch-objs += hyn_chips/hyn_cst66xx.o
hynitron_touch-objs += hyn_chips/hyn_cst3240.o
hynitron_touch-objs += hyn_chips/hyn_cst92xx.o
hynitron_touch-objs += hyn_chips/hyn_cst3xx.o
hynitron_touch-objs += hyn_chips/hyn_cst1xx.o
hynitron_touch-objs += hyn_chips/hyn_cst7xx.o
hynitron_touch-objs += hyn_chips/hyn_cst8xxT.o
hynitron_touch-objs += hyn_chips/hyn_cst7xx.o
4、sys节点操作
1、升级
通过文件升级
adb push xxx.bin /sdcard/app.bin
adb shell "echo fd>/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpfwver"
通过dump升级(GKI version)
adb push xxx.bin /sdcard/app.bin
adb shell "cd /sys/hynitron_debug && echo fwstart>./hyndumpfw && dd if=/sdcard/app.bin of=./hyndumpfw && echo fwend>./hyndumpfw"
2、write
eg:写 d1 01 02 03 04
echo w d1 01 02 03 04 >/sys/hynitron_debug/hyntpdbg
3、read
eg 读 20 byte
echo r 20 >/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpdbg
3、read reg max reg长度4 byte max read 256 byte
eg:写 d1 01 读 2 byte
echo w d1 01 r 2 >/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpdbg
eg:写 d1 01 02 03 读 20 byte
echo w d1 01 02 03 r 20 >/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpdbg
如果reg 不变可以直接用 cat /sys/hynitron_debug/hyntpdbg 读reg沿用上次的操作
4、调试log debug
echo 7 >/proc/sys/kernel/printk
echo log,3>/sys/hynitron_debug/hyntpdbg
5、读版TP_FW本号
cat /sys/hynitron_debug/hyntpfwver
6、tp0 自测(需要提前准备自测配置文件)
cat /sys/hynitron_debug/hynselftest
7、充电模式进入和退出
enter
echo c1>/sys/hynitron_debug/hynswitchmode
exit
echo c0>/sys/hynitron_debug/hynswitchmode
8、手套模式进入和退出
enter
echo g1>/sys/hynitron_debug/hynswitchmode
exit
echo g0>/sys/hynitron_debug/hynswitchmode