diff options
author | Sumit Semwal <sumit.semwal@linaro.org> | 2020-05-06 18:01:42 +0530 |
---|---|---|
committer | Sumit Semwal <sumit.semwal@linaro.org> | 2021-05-26 23:26:33 +0530 |
commit | ea27c1dfa7b7cb83288e6104cb88622074f0e2aa (patch) | |
tree | 3b9fa3821bae55bd9afe6142ae2da71d653cc080 | |
parent | de16c6c5ca7ec889f8d774effd3301e22f7daccb (diff) |
input: touchscreen: stm: downstream snapshot
Taken from https://android.googlesource.com/kernel/msm
aosp/android-msm-crosshatch-4.9-r-preview-2 branch.
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
34 files changed, 35808 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/stm/Kconfig b/drivers/input/touchscreen/stm/Kconfig new file mode 100644 index 000000000000..0c747d2cdce4 --- /dev/null +++ b/drivers/input/touchscreen/stm/Kconfig @@ -0,0 +1,30 @@ +# +# STMicroelectronics TOUCH driver configuration +# + +config TOUCHSCREEN_FTS + tristate "STMicroelectronics i2c multitouch touchscreen - FingerTipS (FTM5)" + depends on I2C + select TOUCHSCREEN_HEATMAP + help + Say Y here to enable STMicroelectronics (FTM5) touchscreen support. + If unsure, say N. + To compile this driver as a module, choose M here: the module + will be called fts_touch. + + +config TOUCHSCREEN_FTM4 + tristate "STMicroelectronics i2c multitouch touchscreen - FTM4 with FingerTipS" + depends on I2C + help + Say Y here to enable STMicroelectronics touchscreen support. + If unsure, say N. + To compile this driver as a module, choose M here: the module + will be called fts_touch. + +config TOUCHSCREEN_FTM4_SHOW_EVENTS + bool "Enable debug of FTM4 events" + depends on TOUCHSCREEN_FTM4 + help + Say Y here to enable dumping of touch driver events. This should + only be enabled for debugging and not for shipping code. diff --git a/drivers/input/touchscreen/stm/Makefile b/drivers/input/touchscreen/stm/Makefile new file mode 100644 index 000000000000..9d20024bd90f --- /dev/null +++ b/drivers/input/touchscreen/stm/Makefile @@ -0,0 +1,11 @@ +# FTM5 support +obj-$(CONFIG_TOUCHSCREEN_FTS) += ftm5.o +ftm5-objs = fts.o fts_proc.o +ftm5-objs += \ + fts_lib/ftsCompensation.o fts_lib/ftsCore.o fts_lib/ftsError.o \ + fts_lib/ftsFrame.o fts_lib/ftsIO.o fts_lib/ftsTest.o fts_lib/ftsTime.o \ + fts_lib/ftsTool.o fts_lib/ftsFlash.o fts_lib/ftsGesture.o + +# Legacy driver +obj-$(CONFIG_TOUCHSCREEN_FTM4) += ftm4.o +ftm4-objs += ftm4_ts.o ftm4_fwu.o ftm4_pdc.o diff --git a/drivers/input/touchscreen/stm/ftm4_fwu.c b/drivers/input/touchscreen/stm/ftm4_fwu.c new file mode 100644 index 000000000000..76e8db5be4ff --- /dev/null +++ b/drivers/input/touchscreen/stm/ftm4_fwu.c @@ -0,0 +1,960 @@ +/******************** (C) COPYRIGHT 2012 STMicroelectronics ******************** +* +* File Name : ftm4_fwu.c +* Authors : AMS(Analog Mems Sensor) Team +* Description : FTS Capacitive touch screen controller (FingerTipS) +* +******************************************************************************** +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES +* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE +* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +* +* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS. +*******************************************************************************/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/firmware.h> +#include <linux/slab.h> +#include <asm/uaccess.h> +#include <linux/hrtimer.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> + +#include "ftm4_ts.h" + +#define FTS64FILE_SIGNATURE 0xaaaa5555 + +enum { + BUILT_IN = 0, + UMS, + NONE, + FFU, +}; + +struct fts64_header { + unsigned int signature; + unsigned short fw_ver; + unsigned char fw_id; + unsigned char reserved1; + unsigned char internal_ver[8]; + unsigned char released_ver[8]; + unsigned int reserved2; + unsigned int checksum; +}; + +bool get_pure_autotune_status(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char addrs[3]; + unsigned char buf[5]; + bool ret = false; + int doffset = 1; + + if (info->digital_rev == FTS_DIGITAL_REV_1) + doffset = 0; + + addrs[0] = 0xd0; + addrs[1] = 0x00; + addrs[2] = 0x4E; + + rc = info->fts_read_reg(info, addrs, 3, buf, 4); + if (rc < 0) { + tsp_debug_err(info->dev, + "%s: PureAutotune Information Read Fail!!" + "[Data : %2X%2X]\n", + __func__, buf[0 + doffset], + buf[1 + doffset]); + } else { + if ((buf[0 + doffset] == 0xA5) && (buf[1 + doffset] == 0x96)) + ret = 1; + tsp_debug_info(info->dev, + "%s: PureAutotune Information !! " + "[Data : %2X%2X]\n", __func__, + buf[0 + doffset], + buf[1 + doffset]); + } + return ret; +} +EXPORT_SYMBOL(get_pure_autotune_status); + +static bool get_afe_status(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char addrs[3]; + unsigned char buf[5]; + bool ret = false; + int doffset = 1; + + if (info->digital_rev == FTS_DIGITAL_REV_1) + doffset = 0; + + addrs[0] = 0xd0; + addrs[1] = 0x00; + addrs[2] = 0x52; + + rc = info->fts_read_reg(info, addrs, 3, buf, 4); + if (rc < 0) { + tsp_debug_err(info->dev, + "%s: Read Fail - Final AFE [Data :" + " %2X] AFE Ver [Data : %2X]\n", + __func__, + buf[0 + doffset], + buf[1 + doffset]); + return rc; + } + + if (buf[0 + doffset]) + ret = true; + + tsp_debug_info(info->dev, + "%s: Final AFE [Data : %2X] AFE Ver " + "[Data : %2X]\n", + __func__, + buf[0 + doffset], + buf[1 + doffset]); + + return ret; +} + +int fts_fw_wait_for_specific_event(struct fts_ts_info *info, + unsigned char eid0, unsigned char eid1, unsigned char eid2) +{ + int rc = 0; + unsigned char addrs; + unsigned char data[FTS_EVENT_SIZE]; + int retry = 0; + + memset(data, 0x0, FTS_EVENT_SIZE); + + addrs = READ_ONE_EVENT; + + while (info->fts_read_reg(info, &addrs, 1, (unsigned char *)data, + FTS_EVENT_SIZE)) { + if (data[0]) { + if ((data[0] == eid0) && (data[1] == eid1) && + (data[2] == eid2)) { + rc = 0; + break; + } else { + tsp_debug_dbg(info->dev, + "%s: %2X, %2X, %2X, %2X\n", + __func__, data[0], data[1], + data[2], data[3]); + } + } + if (retry++ > FTS_RETRY_COUNT * 15) { + rc = -1; + tsp_debug_err(info->dev, + "%s: Time Over ( %2X, %2X, %2X, %2X )\n", + __func__, data[0], data[1], + data[2], data[3]); + break; + } + fts_delay(20); + } + + return rc; +} + +int fts_fw_wait_for_event(struct fts_ts_info *info, unsigned char eid0, + unsigned char eid1) +{ + int rc = 0; + unsigned char addrs; + unsigned char data[FTS_EVENT_SIZE]; + int retry = 0; + + memset(data, 0x0, FTS_EVENT_SIZE); + + addrs = READ_ONE_EVENT; + + while (info->fts_read_reg(info, &addrs, 1, (unsigned char *)data, + FTS_EVENT_SIZE)) { + if ((data[0] == EVENTID_STATUS_EVENT) || + (data[0] == EVENTID_ERROR)) { + if ((data[0] == EVENTID_STATUS_EVENT) && + (data[1] == eid0) && (data[2] == eid1)) { + break; + } else if ((data[0] == EVENTID_STATUS_EVENT) && + (data[1] == STATUS_EVENT_FORCE_CAL_DONE)) { + break; + } else { + tsp_debug_dbg(info->dev, + "%s: %2X,%2X,%2X,%2X\n", + __func__, + data[0], + data[1], + data[2], + data[3]); + } + } + + if (retry++ > FTS_RETRY_COUNT * 15) { + rc = -1; + tsp_debug_err(info->dev, + "%s: Time Over (%2X,%2X,%2X,%2X)\n", + __func__, + data[0], + data[1], + data[2], + data[3]); + break; + } + fts_delay(20); + } + + return rc; +} + +void fts_execute_autotune(struct fts_ts_info *info) +{ + int ret = 0; + unsigned char regData[4]; /* {0xC1, 0x0E}; */ + bool bFinalAFE = false; + bool NoNeedAutoTune = false; /* default for factory */ + + bFinalAFE = get_afe_status(info); + + /* Check flag and decide cx_tune */ + NoNeedAutoTune = get_pure_autotune_status(info); + + tsp_debug_info(info->dev, + "%s: AFE(%d), NoNeedAutoTune(%d)\n", __func__, + bFinalAFE, NoNeedAutoTune); + + if ((!NoNeedAutoTune) || (info->o_afe_ver != info->afe_ver)) { + info->fts_command(info, CX_TUNNING); + fts_delay(300); + fts_fw_wait_for_event(info, STATUS_EVENT_MUTUAL_AUTOTUNE_DONE, + 0x00); + + info->fts_command(info, SELF_AUTO_TUNE); + fts_delay(300); + fts_fw_wait_for_event(info, STATUS_EVENT_SELF_AUTOTUNE_DONE, + 0x00); + + if (NoNeedAutoTune) { + tsp_debug_info(info->dev, + "%s: AFE_status(%d) write ( C8 01 )\n", + __func__, bFinalAFE); + + regData[0] = 0xC8; + regData[1] = 0x01; + ret = info->fts_write_reg(info, regData, 2); + if (ret < 0) { + tsp_debug_err(info->dev, + "%s: Flash Back up PureAutotune" + "Fail (Clear)\n", __func__); + } + + fts_delay(20); + fts_fw_wait_for_event(info, + STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH, + 0x00); + } + + info->fts_command(info, FTS_CMD_SAVE_CX_TUNING); + fts_delay(230); + fts_fw_wait_for_event(info, + STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE, 0x00); + + info->fts_command(info, FTS_CMD_SAVE_FWCONFIG); + fts_delay(230); + fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CONFIG, + 0x00); + + /* Reset FTS */ + info->fts_systemreset(info); + fts_delay(20); + /* wait for ready event */ + info->fts_wait_for_ready(info); + } +} + +#define FW_IMAGE_NAME_D2_TB_INTEG "tsp_stm/stm_tb_integ.fw" +#define FW_IMAGE_NAME_D2_Z2A "tsp_stm/stm_z2a.fw" +#define FW_IMAGE_NAME_D2_Z2I "tsp_stm/stm_z2i.fw" +#define CONFIG_ID_D1_S 0x2C +#define CONFIG_ID_D2_TR 0x2E +#define CONFIG_ID_D2_TB 0x30 +#define CONFIG_OFFSET_BIN_D1 0xf822 +#define CONFIG_OFFSET_BIN_D2 0x1E822 +#define RX_OFFSET_BIN_D2 0x1E834 +#define TX_OFFSET_BIN_D2 0x1E835 + +#define FW_IMAGE_SIZE_D3 (256 * 1024) +#define SIGNEDKEY_SIZE (256) + +static int wait_for_flash_ready(struct fts_ts_info *info, uint8_t type) +{ + uint8_t cmd[2] = {FLASH_CMD_READ_REGISTER, type}; + uint8_t readData; + int i, res = -1; + + tsp_debug_info(info->dev, "[wait_for_flash_ready" + " Waiting for flash ready\n"); + + for (i = 0; i < 1000 && res != 0; i++) { + info->fts_read_reg(info, cmd, sizeof(cmd), &readData, 1); + res = readData & 0x80; + fts_delay(50); + } + + if (i >= 1000 && res != 0) { + tsp_debug_err(info->dev, "[wait_for_flash_ready]" + " Wait for flash TIMEOUT! ERROR\n"); + return 0; + } + + tsp_debug_info(info->dev, "[wait_for_flash_ready]" + " Flash READY!\n"); + + return 1; +} + +static int start_flash_dma(struct fts_ts_info *info) +{ + int status; + uint8_t cmd[3] = {FLASH_CMD_WRITE_REGISTER, + FLASH_DMA_CODE0, FLASH_DMA_CODE1}; + + tsp_debug_info(info->dev, + "[start_flash_dma] Command flash DMA ...\n"); + info->fts_write_reg(info, cmd, sizeof(cmd)); + + status = wait_for_flash_ready(info, FLASH_DMA_CODE0); + + if (status != true) { + tsp_debug_err(info->dev, + "[start_flash_dma] start_flash_dma: ERROR\n"); + return false; + } + tsp_debug_info(info->dev, "[start_flash_dma] flash DMA DONE!\n"); + + return true; +} + +static int fillFlash(struct fts_ts_info *info, uint32_t address, uint8_t *data, + int size) +{ + int remaining; + int toWrite = 0; + int byteBlock = 0; + int wheel = 0; + uint32_t addr = 0; + int res; + int delta; + + uint8_t buff[DMA_CHUNK + 3] = {0}; + + remaining = size; + while (remaining > 0) { + byteBlock = 0; + addr = 0; + tsp_debug_info(info->dev, + "[fillFlash] [%d] Write data to memory.\n", + wheel); + while (byteBlock < FLASH_CHUNK && remaining > 0) { + buff[0] = FLASH_CMD_WRITE_64K; + if (remaining >= DMA_CHUNK) { + if ((byteBlock + DMA_CHUNK) <= FLASH_CHUNK) { + toWrite = DMA_CHUNK; + remaining -= DMA_CHUNK; + byteBlock += DMA_CHUNK; + } else { + delta = FLASH_CHUNK - byteBlock; + toWrite = delta; + remaining -= delta; + byteBlock += delta; + } + } else { + if ((byteBlock + remaining) <= FLASH_CHUNK) { + toWrite = remaining; + byteBlock += remaining; + remaining = 0; + + } else { + delta = FLASH_CHUNK - byteBlock; + toWrite = delta; + remaining -= delta; + byteBlock += delta; + } + } + + buff[1] = (uint8_t) ((addr & 0x0000FF00) >> 8); + buff[2] = (uint8_t) (addr & 0x000000FF); + memcpy(&buff[3], data, toWrite); + info->fts_write_reg(info, buff, 3 + toWrite); + + addr += toWrite; + data += toWrite; + } + + /* configuring the DMA */ + tsp_debug_info(info->dev, + "[fillFlash] [%d] Configure DMA\n", wheel); + byteBlock = byteBlock / 4 - 1; + + buff[0] = FLASH_CMD_WRITE_REGISTER; + buff[1] = FLASH_DMA_CONFIG; + buff[2] = 0x00; + buff[3] = 0x00; + + addr = address + ((wheel * FLASH_CHUNK)/4); + buff[4] = (uint8_t) ((addr & 0x000000FF)); + buff[5] = (uint8_t) ((addr & 0x0000FF00) >> 8); + buff[6] = (uint8_t) (byteBlock & 0x000000FF); + buff[7] = (uint8_t) ((byteBlock & 0x0000FF00) >> 8); + buff[8] = 0x00; + + info->fts_write_reg(info, buff, 9); + fts_delay(10); + + tsp_debug_info(info->dev, + "[fillFlash] [%d] Start flash DMA\n", wheel); + res = start_flash_dma(info); + if (res < true) { + tsp_debug_err(info->dev, + "[fillFlash] Error during flashing DMA! ERROR\n"); + return false; + } + tsp_debug_info(info->dev, + "[fillFlash] [%d] DMA done\n", wheel); + + wheel++; + } + return true; +} + +uint32_t convU8toU32(uint8_t *src) +{ + uint32_t tmpData; + + tmpData = (uint32_t) (((src[3] & 0xFF) << 24) + + ((src[2] & 0xFF) << 16) + + ((src[1] & 0xFF) << 8) + + (src[0] & 0xFF)); + + return tmpData; +} + +static int parseBinFile(struct fts_ts_info *info, uint8_t *data, + int fw_size, + struct FW_FTB_HEADER *fw_header, + int keep_cx) +{ + int dimension, index; + uint32_t temp; + int file_type; + + /* start the parsing */ + index = 0; + fw_header->signature = convU8toU32(&data[index]); + if (fw_header->signature == FW_HEADER_FTB_SIGNATURE) { + tsp_debug_info(info->dev, + "[parseBinFile] FW Signature - ftb file\n"); + file_type = BIN_FTB; + } else { + tsp_debug_info(info->dev, + "[parseBinFile] FW Signature - ftsxxx file. %08X\n", + fw_header->signature); + file_type = BIN_FTS256; + return file_type; + } + + index += FW_BYTES_ALLIGN; +#ifdef FTS_USE_FTB_1 + fw_header->ftb_ver = convU8toU32(&data[index]); + if (fw_header->ftb_ver != FW_FTB_VER) { + tsp_debug_err(info->dev, + "[parseBinFile] Wrong" " ftb_version %08X ... ERROR\n", + fw_header->ftb_ver); + return false; + } +#endif /* FTS_USE_FTB_1 */ + + index += FW_BYTES_ALLIGN; + fw_header->target = convU8toU32(&data[index]); + if (fw_header->target != 0x00007036) { + tsp_debug_err(info->dev, + "[parseBinFile] Wrong target version %08X ... ERROR\n", + fw_header->target); + return false; + } + + index += FW_BYTES_ALLIGN; + fw_header->fw_id = convU8toU32(&data[index]); + + index += FW_BYTES_ALLIGN; + fw_header->fw_ver = convU8toU32(&data[index]); + info->fw_version_of_bin = fw_header->fw_ver; + + index += FW_BYTES_ALLIGN; + fw_header->cfg_id = convU8toU32(&data[index]); + + index += FW_BYTES_ALLIGN; + fw_header->cfg_ver = convU8toU32(&data[index]); + info->config_version_of_bin = fw_header->cfg_ver; + + index += FW_BYTES_ALLIGN * 3; /* skip 2 reserved data */ + fw_header->bl_fw_ver = convU8toU32(&data[index]); + index += FW_BYTES_ALLIGN; + + fw_header->ext_ver = convU8toU32(&data[index]); + + tsp_debug_info(info->dev, + "[parseBinFile] Version : External" + " = %04X, FW = %04X, CFG = %04X\n", + fw_header->ext_ver, + fw_header->fw_ver, + fw_header->cfg_ver); + + index += FW_BYTES_ALLIGN; + fw_header->sec0_size = convU8toU32(&data[index]); + + index += FW_BYTES_ALLIGN; + fw_header->sec1_size = convU8toU32(&data[index]); + + tsp_debug_info(info->dev, + "[parseBinFile] sec0_size = %08X" + " (%d bytes), sec1_size = %08X (%d bytes)\n", + fw_header->sec0_size, + fw_header->sec0_size, + fw_header->sec1_size, + fw_header->sec1_size); + + index += FW_BYTES_ALLIGN; + fw_header->sec2_size = convU8toU32(&data[index]); + + index += FW_BYTES_ALLIGN; + fw_header->sec3_size = convU8toU32(&data[index]); + + tsp_debug_info(info->dev, + "[parseBinFile] sec2_size = %08X" + " (%d bytes), sec3_size = %08X (%d bytes)\n", + fw_header->sec2_size, + fw_header->sec2_size, + fw_header->sec3_size, + fw_header->sec3_size); + + index += FW_BYTES_ALLIGN; + fw_header->hdr_crc = convU8toU32(&data[index]); + + if (!keep_cx) { + dimension = fw_header->sec0_size + fw_header->sec1_size + + fw_header->sec2_size + fw_header->sec3_size; + + temp = fw_size; + } else { + /* sec2 may contain cx data (future implementation) + * sec3 atm not used */ + dimension = fw_header->sec0_size + fw_header->sec1_size; + temp = fw_size - fw_header->sec2_size - fw_header->sec3_size; + } + + if (dimension + FW_HEADER_SIZE + FW_BYTES_ALLIGN != temp) { + tsp_debug_info(info->dev, + "[parseBinFile] Read only %d" + " instead of %d... ERROR\n", + fw_size, dimension + + FW_HEADER_SIZE + + FW_BYTES_ALLIGN); + + return false; + } + + return file_type; +} + +static int fts_check_erase_done(struct fts_ts_info *info) +{ + int timeout = 60; /* 3 sec timeout */ + unsigned char addrs[2] = {0xF9, 0x02}; + unsigned char val[1]; + int rc = 0; + + do { + info->fts_read_reg(info, &addrs[0], 2, (unsigned char *)val, 1); + + if ((val[0] & 0x80) != 0x80) + break; + + fts_delay(50); + timeout--; + } while (timeout != 0); + + if (timeout == 0) + rc = -1; + + return rc; +} + +int fw_download(struct fts_ts_info *info, uint8_t *pFilename, + struct FW_FTB_HEADER *fw_Header, int8_t block_type) +{ + uint32_t FTS_TOTAL_SIZE = (256 * 1024); /* Total 256kB */ + int HEADER_DATA_SIZE = 32; + + int res = 0, rc = 0, i = 0; + uint8_t addrs[8] = {0}; + + /* System reset */ + /* System Reset ==> F7 52 34 */ + + addrs[0] = 0xF7; + addrs[1] = 0x52; + addrs[2] = 0x34; + info->fts_write_reg(info, &addrs[0], 3); + fts_delay(30); + + /* Unlock Flash */ + /* Unlock Flash Command ==> F7 74 45 */ + addrs[0] = 0xF7; + addrs[1] = 0x74; + addrs[2] = 0x45; + info->fts_write_reg(info, &addrs[0], 3); + fts_delay(100); + + /* Unlock Erase Operation */ + addrs[0] = 0xFA; + addrs[1] = 0x72; + addrs[2] = 0x01; + info->fts_write_reg(info, &addrs[0], 3); + fts_delay(30); + + /* Erase Partial Flash */ + for (i = 0; i < 64; i++) { + /* skip CX2 area (page 61 and page 62) */ + if ((i == 61) || (i == 62)) + continue; + + addrs[0] = 0xFA; + addrs[1] = 0x02; + addrs[2] = (0x80 + i) & 0xFF; + info->fts_write_reg(info, &addrs[0], 3); + rc = fts_check_erase_done(info); + if (rc < 0) + return rc; + } + + /* Unlock Programming operation */ + addrs[0] = 0xFA; + addrs[1] = 0x72; + addrs[2] = 0x02; + info->fts_write_reg(info, &addrs[0], 3); + fts_delay(100); + + /* Write to FLASH */ + if (block_type == BIN_FTB) { + tsp_debug_info(info->dev, + "[fw_download] Start sec0 program\n"); + + res = fillFlash(info, + FLASH_ADDR_CODE, + &pFilename[FW_HEADER_SIZE], + fw_Header->sec0_size); + + if (res != true) { + tsp_debug_err(info->dev, + "[fw_download] Error - load sec0 program\n"); + return false; + } + tsp_debug_info(info->dev, + "[fw_download] load sec0 program DONE!\n"); + tsp_debug_info(info->dev, + "[fw_download] Start sec1 program\n"); + + res = fillFlash(info, + FLASH_ADDR_CONFIG, + &pFilename[FW_HEADER_SIZE + + fw_Header->sec0_size], + fw_Header->sec1_size); + + if (res != true) { + tsp_debug_err(info->dev, + "[fw_download] Error - load sec1 program\n"); + return false; + } + tsp_debug_info(info->dev, + "[fw_download] load sec1 program DONE!\n"); + + tsp_debug_info(info->dev, + "[fw_download] Flash burn COMPLETED!\n"); + } else { + tsp_debug_info(info->dev, + "[fw_download] Start firmware downloading\n"); + res = fillFlash(info, FLASH_ADDR_CODE, + &pFilename[HEADER_DATA_SIZE], FTS_TOTAL_SIZE); + if (res != true) { + tsp_debug_err(info->dev, + "[fw_download] Error - load sec0 program\n"); + return false; + } + } + + /* System reset */ + addrs[0] = 0xF7; + addrs[1] = 0x52; + addrs[2] = 0x34; + info->fts_write_reg(info, &addrs[0], 3); + if (fts_cmd_completion_check(info, 0x10, 0x00, 0x00) < 0) { + tsp_debug_err(info->dev, + "[fw_download] Error - System Reset FAILED\n"); + return false; + } + + return true; +} + +static int fts_fw_compare(struct fts_ts_info *info, const struct firmware *fw) +{ + u32 bin_fw_ver_addr_1 = 0; + u32 bin_fw_ver_addr_2 = 0; + u32 bin_fw_ver_offset = 24; + u8 buf[2] = {0}; + struct fts_version *binary = NULL; + struct fts_version *device = &info->ic_fw_ver; + int update = 0; + + if ((u32)fw->size < bin_fw_ver_offset) { + tsp_debug_err(info->dev, + " fw->size(0x%08X) < bin_fw_ver_offset(0x%08X)\n", + (u32)fw->size, bin_fw_ver_offset); + update = 0; + goto error; + } + + bin_fw_ver_addr_1 = (u32)fw->size - bin_fw_ver_offset; + bin_fw_ver_addr_2 = bin_fw_ver_addr_1 + 1; + tsp_debug_info(info->dev, + "%s: bin_fw_ver_addr_1 = 0x%08X , bin_fw_ver_addr_2 = 0x%08X\n", + __func__, bin_fw_ver_addr_1, bin_fw_ver_addr_2); + + binary = kzalloc(sizeof(struct fts_version), GFP_KERNEL); + if (binary == NULL) { + tsp_debug_err(info->dev, "failed to kzalloc binary\n"); + update = 0; + goto error; + } + + buf[0] = fw->data[bin_fw_ver_addr_1]; + buf[1] = fw->data[bin_fw_ver_addr_2]; + + binary->build = (buf[0] >> 4) & 0x0F; + binary->major = buf[0] & 0x0F; + binary->minor = buf[1]; + + if (binary->major != device->major) { + update = 1; + } else { + if (binary->minor != device->minor) + update = 1; + else if (binary->build > device->build) + update = 1; + } + + tsp_debug_info(info->dev, + "%s : binary[%d.%02d.%d] device[%d.%02d.%d]" + " -> update: %d\n", __func__, + binary->major, binary->minor, binary->build, + device->major, device->minor, device->build, + update); + +error: + if (binary) + kfree(binary); + + return update; +} + +void fts_fw_init(struct fts_ts_info *info) +{ + tsp_debug_info(info->dev, "%s\n", __func__); + + info->fts_command(info, FTS_CMD_TRIM_LOW_POWER_OSCILLATOR); + fts_delay(200); + info->fts_command(info, FTS_CMD_SAVE_CX_TUNING); + fts_delay(230); + fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE, 0x00); + + fts_get_afe_info(info); + + fts_execute_autotune(info); + + info->fts_command(info, SENSEON); + + fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE, 0x00); + + info->fts_interrupt_set(info, INT_ENABLE); +} + +static int fts_fw_check(struct fts_ts_info *info) +{ + int retval = 0; + + retval = fts_systemreset(info); + if (retval < 0) + return retval; + + retval = fts_wait_for_ready(info); + if (retval < 0) + return retval; + + retval = fts_read_chip_id(info); + if (retval < 0) + return retval; + + return retval; +} + +static int fts_fw_update(struct fts_ts_info *info) +{ + const struct firmware *fw_entry = NULL; + unsigned char *fw_data = NULL; + char fw_path[FTS_MAX_FW_PATH]; + const struct FW_FTB_HEADER *header; + int fw_size; + int fw_type; + int keep_cx; + int retval = 0; + struct FW_FTB_HEADER fw_ftbHeader; + + if (info->fts_power_state != FTS_POWER_STATE_ACTIVE) { + tsp_debug_err(info->dev, + "%s : FTS_POWER_STATE is not ACTIVE\n", __func__); + return -EPERM; + } + + if (info->test_fwpath[0]) { + strlcpy(fw_path, &info->test_fwpath[0], sizeof(fw_path)); + } else if(info->board->firmware_name) { + /* A pointer and size of buffer for binary file */ + strlcpy(fw_path, &info->board->firmware_name[0], sizeof(fw_path)); + } else { + tsp_debug_err(info->dev, "%s : no firmware file\n", __func__); + return -EPERM; + } + + tsp_debug_info(info->dev, + "%s : firmware name : %s\n", __func__, fw_path); + + retval = request_firmware(&fw_entry, fw_path, info->dev); + if (retval) { + tsp_debug_err(info->dev, + "%s : Firmware image %s not available\n", __func__, + fw_path); + return retval; + } + + if (!fts_fw_compare(info, fw_entry)) { + tsp_debug_info(info->dev, + "%s : skip fw_upgrade(ic_fw_ver == bin_fw_ver)\n", + __func__); + goto out; + } + + fw_size = fw_entry->size; + fw_data = (unsigned char *)fw_entry->data; + header = (struct FW_FTB_HEADER *)fw_data; + + info->fw_version_of_bin = header->fw_ver; + info->config_version_of_bin = header->cfg_ver; + /* saver previous afe version before downloading */ + info->o_afe_ver = info->afe_ver; +#ifdef FTS_FTB_STYLE_2 + info->fw_main_version_of_bin = + ((header->ext_ver & 0xff)<<8) + + ((header->ext_ver >> 8) & 0xff); + + tsp_debug_info(info->dev, + "Bin Firmware Version : 0x%04X " + "Bin Config Version : 0x%04X " + "Bin Main Firmware Version : 0x%04X ", + info->fw_version_of_bin, + info->config_version_of_bin, + info->fw_main_version_of_bin); +#else /* FTS_FTB_STYLE_2 */ + tsp_debug_info(info->dev, + "Bin Firmware Version : 0x%04X " + "Bin Config Version : 0x%04X ", + info->fw_version_of_bin, + info->config_version_of_bin); +#endif + memcpy(&fw_ftbHeader, fw_data, sizeof(struct FW_FTB_HEADER)); + + tsp_debug_info(info->dev, + "[flashProcedure] Firmware size : %d\n", fw_size); + keep_cx = 0; + + fw_type = parseBinFile(info, fw_data, fw_size, &fw_ftbHeader, keep_cx); + if (fw_type == false) { + tsp_debug_err(info->dev, + "[flashProcedure] Error - FW is not appreciate\n"); + retval = -EINVAL; + goto out; + } + + retval = fw_download(info, fw_data, &fw_ftbHeader, fw_type); + if (retval == 0) { + tsp_debug_err(info->dev, + "[flashProcedure] Error - Firmware update is not completed.\n"); + retval = -EIO; + goto out; + } + + fts_fw_init(info); + retval = fts_fw_check(info); + if (retval < 0 || + info->flash_corruption_info.fw_broken || + info->flash_corruption_info.cfg_broken || + info->flash_corruption_info.cx_broken) { + retval = -EIO; + goto out; + } + + fts_get_version_info(info); + if (fts_fw_compare(info, fw_entry)) { + tsp_debug_err(info->dev, + "[flashProcedure] Firmware update failed\n"); + retval = -EIO; + goto out; + } + + tsp_debug_info(info->dev, + "[flashProcedure] Firmware update is done successfully.\n"); + retval = 0; +out: + if (fw_entry) + release_firmware(fw_entry); + return retval; +} + +int fts_fw_verify_update(struct fts_ts_info *info) +{ + int retry = 0; + + info->fts_irq_enable(info, false); + while (retry++ < FTS_FW_UPDATE_RETRY) { + tsp_debug_info(info->dev, + "[fw_update] try:%d\n", retry); + if (0 == fts_fw_update(info)) { + info->fts_irq_enable(info, true); + return 0; + } + } + info->fts_irq_enable(info, true); + return -EIO; +} +EXPORT_SYMBOL(fts_fw_verify_update); diff --git a/drivers/input/touchscreen/stm/ftm4_pdc.c b/drivers/input/touchscreen/stm/ftm4_pdc.c new file mode 100644 index 000000000000..83daa211f09a --- /dev/null +++ b/drivers/input/touchscreen/stm/ftm4_pdc.c @@ -0,0 +1,2265 @@ +/******************** (C) COPYRIGHT 2012 STMicroelectronics ******************** +* +* File Name : ftm4_pdc.c +* Authors : AMS(Analog Mems Sensor) Team +* Description : FTS Capacitive touch screen controller (FingerTipS) +* +******************************************************************************** +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES +* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE +* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +* +* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS. +*******************************************************************************/ + +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/serio.h> +#include <linux/init.h> +#include <linux/pm.h> +#include <linux/delay.h> +#include <linux/ctype.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/power_supply.h> +#include <linux/firmware.h> +#include <linux/regulator/consumer.h> +#include <linux/of_gpio.h> +#include <linux/device.h> +#include <linux/list.h> +#include "ftm4_ts.h" + +#define TSP_FACTEST_RESULT_PASS 2 +#define TSP_FACTEST_RESULT_FAIL 1 +#define TSP_FACTEST_RESULT_NONE 0 + +#define BUFFER_MAX ((256 * 1024) - 16) +#define READ_CHUNK_SIZE 128 + +#define FTS_F_WIX1_ADDR 0x1FE7 +#define FTS_S_WIX1_ADDR 0x1FE8 +#define FTS_F_WIX2_ADDR 0x18FD +#define FTS_S_WIX2_ADDR 0x1929 +#define FTS_WATER_SELF_RAW_ADDR 0x1E + +#define FTS_MAX_TX_LENGTH 44 +#define FTS_MAX_RX_LENGTH 64 + +#define FTS_CX2_READ_LENGTH 4 +#define FTS_CX2_ADDR_OFFSET 3 +#define FTS_CX2_TX_START 0 +#define FTS_CX2_BASE_ADDR 0x1000 +#define SEC_CMD_STR_LEN 12 + +#define DEBUG_MSG 1 +enum { + TYPE_RAW_DATA = 0, + TYPE_FILTERED_DATA = 2, + TYPE_STRENGTH_DATA = 4, + TYPE_BASELINE_DATA = 6 +}; + +enum { + BUILT_IN = 0, + UMS, +}; + +enum CMD_STATUS { + CMD_STATUS_WAITING = 0, + CMD_STATUS_RUNNING, + CMD_STATUS_OK, + CMD_STATUS_FAIL, + CMD_STATUS_NOT_APPLICABLE, +}; + +static void get_fw_ver_bin(void *device_data); +static void get_fw_ver_ic(void *device_data); +static void get_config_ver(void *device_data); +static void get_threshold(void *device_data); +static void get_x_num(void *device_data); +static void get_y_num(void *device_data); +static void run_rawcap_read(void *device_data); +static void get_rawcap(void *device_data); +static void run_ix_data_read(void *device_data); +static void run_ix_data_read_all(void *device_data); +static void run_self_raw_read(void *device_data); +static void run_self_raw_read_all(void *device_data); +static void get_cx_data(void *device_data); +static void run_cx_data_read(void *device_data); +static void get_cx_all_data(void *device_data); +static void get_strength_all_data(void *device_data); +static void set_tsp_test_result(void *device_data); +static void get_tsp_test_result(void *device_data); +static void run_trx_short_test(void *device_data); +static void report_rate(void *device_data); +static void delay(void *device_data); +static void debug(void *device_data); +static void run_autotune_enable(void *device_data); +static void run_autotune(void *device_data); +static void not_support_cmd(void *device_data); + +static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_cmd_status(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_cmd_result(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t cmd_list_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t store_upgrade(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t store_check_fw(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count); +static ssize_t show_version_info(struct device *dev, + struct device_attribute *devattr, char *buf); + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +static void tui_mode_cmd(struct fts_ts_info *info); +#endif + +struct fts_cmd fts_commands[] = { + {FTS_CMD("get_fw_ver_bin", get_fw_ver_bin),}, + {FTS_CMD("get_fw_ver_ic", get_fw_ver_ic),}, + {FTS_CMD("get_config_ver", get_config_ver),}, + {FTS_CMD("get_threshold", get_threshold),}, + {FTS_CMD("get_x_num", get_x_num),}, + {FTS_CMD("get_y_num", get_y_num),}, + {FTS_CMD("run_rawcap_read", run_rawcap_read),}, + {FTS_CMD("get_rawcap", get_rawcap),}, + {FTS_CMD("run_ix_data_read", run_ix_data_read),}, + {FTS_CMD("run_ix_data_read_all", run_ix_data_read_all),}, + {FTS_CMD("run_self_raw_read", run_self_raw_read),}, + {FTS_CMD("run_self_raw_read_all", run_self_raw_read_all),}, + {FTS_CMD("get_cx_data", get_cx_data),}, + {FTS_CMD("run_cx_data_read", run_cx_data_read),}, + {FTS_CMD("get_cx_all_data", get_cx_all_data),}, + {FTS_CMD("get_strength_all_data", get_strength_all_data),}, + {FTS_CMD("set_tsp_test_result", set_tsp_test_result),}, + {FTS_CMD("get_tsp_test_result", get_tsp_test_result),}, + {FTS_CMD("report_rate", report_rate),}, + {FTS_CMD("delay", delay),}, + {FTS_CMD("debug", debug),}, + {FTS_CMD("run_autotune_enable", run_autotune_enable),}, + {FTS_CMD("run_autotune", run_autotune),}, + {FTS_CMD("run_trx_short_test", run_trx_short_test),}, + {FTS_CMD("not_support_cmd", not_support_cmd),}, +}; + +static DEVICE_ATTR(cmd, S_IWUSR | S_IWGRP, NULL, store_cmd); +static DEVICE_ATTR(cmd_status, S_IRUGO, show_cmd_status, NULL); +static DEVICE_ATTR(cmd_result, S_IRUGO, show_cmd_result, NULL); +static DEVICE_ATTR(cmd_list, S_IRUGO, cmd_list_show, NULL); +static DEVICE_ATTR(fw_upgrade, S_IWUSR | S_IWGRP, NULL, store_upgrade); +static DEVICE_ATTR(check_fw, S_IWUSR | S_IWGRP, NULL, store_check_fw); +static DEVICE_ATTR(version, S_IRUGO, show_version_info, NULL); + +static struct attribute *touch_pdc_attributes[] = { + &dev_attr_cmd.attr, + &dev_attr_cmd_status.attr, + &dev_attr_cmd_result.attr, + &dev_attr_cmd_list.attr, + &dev_attr_fw_upgrade.attr, + &dev_attr_check_fw.attr, + &dev_attr_version.attr, + NULL, +}; + +static struct attribute_group touch_pdc_attr_group = { + .attrs = touch_pdc_attributes, +}; + +static ssize_t store_check_fw(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + unsigned int input = 0; + int ret = 0; + + if (sscanf(buf, "%u", &input) != 1) { + tsp_debug_err(&info->client->dev, "%s: Invalid argument\n", __func__); + return -EINVAL; + } + + if (input) { + mutex_lock(&info->device_mutex); + + info->test_fwpath[0] = '\0'; + ret = fts_fw_verify_update(info); + + mutex_unlock(&info->device_mutex); + } + + if (ret) + return ret; + else + return count; +} + +static ssize_t store_upgrade(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + int ret = 0; + + if (strlcpy(&info->test_fwpath[0], buf, count) <= 0) { + tsp_debug_err(&info->client->dev, "%s: invalid firmware name\n", __func__); + return -EINVAL; + } + + mutex_lock(&info->device_mutex); + + ret = fts_fw_verify_update(info); + info->test_fwpath[0] = '\0'; + + mutex_unlock(&info->device_mutex); + + if (ret) + return ret; + else + return count; +} + +static ssize_t show_version_info(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + int offset = 0; + char str[16] = {0}; + int ret = 0; + + mutex_lock(&info->device_mutex); + + if (fts_get_version_info(info) < 0) { + mutex_unlock(&info->device_mutex); + return -EINVAL; + } + + mutex_unlock(&info->device_mutex); + + ret += snprintf(str + ret, sizeof(str) - ret, + "v%d.%02d", info->ic_fw_ver.major, info->ic_fw_ver.minor); + + if (info->ic_fw_ver.build) { + ret += snprintf(str + ret, sizeof(str) - ret, + ".%d", info->ic_fw_ver.build); + } + + offset += snprintf(buf + offset, PAGE_SIZE - offset, "%s\n", str); + + return offset; +} + +static int fts_check_index(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + int node; + + if (info->cmd_param[0] < 0 || + info->cmd_param[0] >= info->SenseChannelLength || + info->cmd_param[1] < 0 || + info->cmd_param[1] >= info->ForceChannelLength) { + snprintf(buff, sizeof(buff), "%s", "NG"); + strncat(info->cmd_result, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_FAIL; + tsp_debug_info(&info->client->dev, + "%s: parameter error: %u,%u\n", + __func__, info->cmd_param[0], info->cmd_param[1]); + node = -1; + return node; + } + node = info->cmd_param[1] * info->SenseChannelLength + + info->cmd_param[0]; + tsp_debug_info(&info->client->dev, "%s: node = %d\n", __func__, node); + return node; +} + +static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + char *cur, *start, *end; + char buff[CMD_STR_LEN] = { 0 }; + int len, i; + struct fts_cmd *ft_cmd_ptr = NULL; + char delim = ','; + bool cmd_found = false; + int param_cnt = 0; + + if (!info) { + tsp_debug_err(&info->client->dev, + "%s: No platform data found\n", __func__); + return -EINVAL; + } + + if (!info->input_dev) { + tsp_debug_err(&info->client->dev, + "%s: No input_dev data found\n", __func__); + return -EINVAL; + } + + if (count > CMD_STR_LEN) { + tsp_debug_err(&info->client->dev, + "%s: overflow command length\n", __func__); + return -EINVAL; + } + + if (info->cmd_is_running == true) { + tsp_debug_err(&info->client->dev, + "ft_cmd: other cmd is running.\n"); + if (strncmp("clear_cover_mode", buf, 16) == 0) { + cancel_delayed_work(&info->cover_cmd_work); + tsp_debug_err(&info->client->dev, + "[cmd is delayed] %d, param = %d, %d\n", + __LINE__, buf[17]-'0', buf[19]-'0'); + info->delayed_cmd_param[0] = buf[17]-'0'; + if (info->delayed_cmd_param[0] > 1) + info->delayed_cmd_param[1] = buf[19]-'0'; + + schedule_delayed_work(&info->cover_cmd_work, + msecs_to_jiffies(10)); + } + return -EBUSY; + } else if (info->reinit_done == false) { + tsp_debug_err(&info->client->dev, + "ft_cmd: reinit is working\n"); + if (strncmp("clear_cover_mode", buf, 16) == 0) { + cancel_delayed_work(&info->cover_cmd_work); + tsp_debug_err(&info->client->dev, + "[cmd is delayed] %d, param = %d, %d\n", + __LINE__, buf[17]-'0', buf[19]-'0'); + info->delayed_cmd_param[0] = buf[17]-'0'; + if (info->delayed_cmd_param[0] > 1) + info->delayed_cmd_param[1] = buf[19]-'0'; + + if (info->delayed_cmd_param[0] == 0) + schedule_delayed_work(&info->cover_cmd_work, + msecs_to_jiffies(300)); + } + } + + /* check lock */ + mutex_lock(&info->cmd_lock); + info->cmd_is_running = true; + mutex_unlock(&info->cmd_lock); + info->cmd_state = 1; + memset(info->cmd_param, 0x00, ARRAY_SIZE(info->cmd_param)); + + len = (int)count; + if (*(buf + len - 1) == '\n') + len--; + memset(info->cmd, 0x00, ARRAY_SIZE(info->cmd)); + memcpy(info->cmd, buf, len); + cur = strchr(buf, (int)delim); + if (cur) + memcpy(buff, buf, cur - buf); + + else + memcpy(buff, buf, len); + tsp_debug_info(&info->client->dev, "COMMAND : %s\n", buff); + + /* find command */ + list_for_each_entry(ft_cmd_ptr, &info->cmd_list_head, list) { + if (!strncmp(buff, ft_cmd_ptr->cmd_name, CMD_STR_LEN)) { + cmd_found = true; + break; + } + } + + /* set not_support_cmd */ + if (!cmd_found) { + list_for_each_entry(ft_cmd_ptr, &info->cmd_list_head, list) { + if (!strncmp + ("not_support_cmd", ft_cmd_ptr->cmd_name, + CMD_STR_LEN)) + break; + } + } + + /* parsing parameters */ + if (cur && cmd_found) { + cur++; + start = cur; + memset(buff, 0x00, ARRAY_SIZE(buff)); + + do { + if (*cur == delim || cur - buf == len) { + end = cur; + memcpy(buff, start, end - start); + *(buff + strnlen(buff, ARRAY_SIZE(buff))) = + '\0'; + if (kstrtoint + (buff, 10, + info->cmd_param + param_cnt) < 0) + goto err_out; + start = cur + 1; + memset(buff, 0x00, ARRAY_SIZE(buff)); + param_cnt++; + } + cur++; + } while (cur - buf <= len); + } + tsp_debug_info(&info->client->dev, "cmd = %s\n", ft_cmd_ptr->cmd_name); + for (i = 0; i < param_cnt; i++) + tsp_debug_info(&info->client->dev, "cmd param %d= %d\n", i, + info->cmd_param[i]); + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode()) + tui_mode_cmd(info); + else +#endif + ft_cmd_ptr->cmd_func(info); + +err_out: + return count; +} + +static ssize_t show_cmd_status(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + char buff[16] = {0}; + + if (!info) { + tsp_debug_err(&info->client->dev, + "%s: No platform data found\n", __func__); + return -EINVAL; + } + + if (!info->input_dev) { + tsp_debug_err(&info->client->dev, + "%s: No input_dev data found\n", __func__); + return -EINVAL; + } + + tsp_debug_info(&info->client->dev, "tsp cmd: status:%d\n", info->cmd_state); + if (info->cmd_state == CMD_STATUS_WAITING) + snprintf(buff, sizeof(buff), "WAITING"); + + else if (info->cmd_state == CMD_STATUS_RUNNING) + snprintf(buff, sizeof(buff), "RUNNING"); + + else if (info->cmd_state == CMD_STATUS_OK) + snprintf(buff, sizeof(buff), "OK"); + + else if (info->cmd_state == CMD_STATUS_FAIL) + snprintf(buff, sizeof(buff), "FAIL"); + + else if (info->cmd_state == CMD_STATUS_NOT_APPLICABLE) + snprintf(buff, sizeof(buff), "NOT_APPLICABLE"); + return snprintf(buf, TSP_BUF_SIZE, "%s\n", buff); +} + +static ssize_t show_cmd_result(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + + if (!info) { + tsp_debug_err(&info->client->dev, + "%s: No platform data found\n", __func__); + return -EINVAL; + } + + if (!info->input_dev) { + tsp_debug_err(&info->client->dev, + "%s: No input_dev data found\n", __func__); + return -EINVAL; + } + + tsp_debug_info(&info->client->dev, "tsp cmd: result: %s\n", + info->cmd_result); + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + info->cmd_state = 0; + return snprintf(buf, TSP_BUF_SIZE, "%s\n", info->cmd_result); +} + +static ssize_t cmd_list_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + int ii = 0; + char buffer[info->cmd_buf_size+CMD_STR_LEN]; + char buffer_name[CMD_STR_LEN]; + + snprintf(buffer, CMD_STR_LEN, "++factory command list++\n"); + while (strncmp(fts_commands[ii].cmd_name, "not_support_cmd", 16) != 0) { + snprintf(buffer_name, CMD_STR_LEN, + "%s\n", fts_commands[ii].cmd_name); + strcat(buffer, buffer_name); + ii++; + } + + tsp_debug_info(&info->client->dev, + "%s: length : %u / %d\n", __func__, + (unsigned int)strlen(buffer), info->cmd_buf_size+CMD_STR_LEN); + + return snprintf(buf, TSP_BUF_SIZE, "%s\n", buffer); +} + +static void set_default_result(struct fts_ts_info *info) +{ + char delim = ':'; + + memset(info->cmd_result, 0x00, ARRAY_SIZE(info->cmd_result)); + memcpy(info->cmd_result, info->cmd, strnlen(info->cmd, CMD_STR_LEN)); + strncat(info->cmd_result, &delim, 1); +} + +static void set_cmd_result(struct fts_ts_info *info, char *buff, int len) +{ + strncat(info->cmd_result, buff, len); +} + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +static void tui_mode_cmd(struct fts_ts_info *info) +{ + char buff[16] = "TUImode:FAIL"; + + set_default_result(info); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} +#endif + +static void not_support_cmd(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[16] = {0}; + + set_default_result(info); + snprintf(buff, sizeof(buff), "%s", "NA"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + tsp_debug_info(&info->client->dev, "%s: \"%s\"\n", __func__, buff); +} + +void procedure_cmd_event(struct fts_ts_info *info, unsigned char *data) +{ + char buff[16] = {0}; + + if ((data[1] == 0x00) && (data[2] == 0x62)) { + snprintf(buff, sizeof(buff), "%d", + *(unsigned short *)&data[3]); + tsp_debug_info(&info->client->dev, "%s: %s\n", "get_threshold", buff); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + + } else if ((data[1] == 0x07) && (data[2] == 0xE7)) { + if (data[3] <= TSP_FACTEST_RESULT_PASS) { + sprintf(buff, "%s", + data[3] == TSP_FACTEST_RESULT_PASS ? "PASS" : + data[3] == TSP_FACTEST_RESULT_FAIL ? "FAIL" : "NONE"); + tsp_debug_info(&info->client->dev, + "%s: success [%s][%d]", "get_tsp_test_result", + data[3] == TSP_FACTEST_RESULT_PASS ? "PASS" : + data[3] == TSP_FACTEST_RESULT_FAIL ? "FAIL" : + "NONE", data[3]); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + } else { + snprintf(buff, sizeof(buff), "%s", "NG"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_FAIL; + tsp_debug_info(&info->client->dev, "%s: %s\n", + "get_tsp_test_result", + buff); + } + } +} +EXPORT_SYMBOL(procedure_cmd_event); + +void fts_print_frame(struct fts_ts_info *info, short *min, short *max) +{ + int i = 0; + int j = 0; + unsigned char *pStr = NULL; + unsigned char pTmp[16] = {0}; + + pStr = kzalloc(6 * (info->SenseChannelLength + 1), GFP_KERNEL); + if (pStr == NULL) { + tsp_debug_info(&info->client->dev, "FTS pStr kzalloc failed\n"); + return; + } + + memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1)); + snprintf(pTmp, sizeof(pTmp), " "); + strncat(pStr, pTmp, 6 * info->SenseChannelLength); + + for (i = 0; i < info->SenseChannelLength; i++) { + snprintf(pTmp, sizeof(pTmp), "Rx%02d ", i); + strncat(pStr, pTmp, 6 * info->SenseChannelLength); + } + + tsp_debug_info(&info->client->dev, "FTS %s\n", pStr); + memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1)); + snprintf(pTmp, sizeof(pTmp), " +"); + strncat(pStr, pTmp, 6 * info->SenseChannelLength); + + for (i = 0; i < info->SenseChannelLength; i++) { + snprintf(pTmp, sizeof(pTmp), "------"); + strncat(pStr, pTmp, 6 * info->SenseChannelLength); + } + + tsp_debug_info(&info->client->dev, "FTS %s\n", pStr); + + for (i = 0; i < info->ForceChannelLength; i++) { + memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1)); + snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", i); + strncat(pStr, pTmp, 6 * info->SenseChannelLength); + + for (j = 0; j < info->SenseChannelLength; j++) { + snprintf(pTmp, sizeof(pTmp), "%5d ", + info->pFrame[(i * info->SenseChannelLength) + j]); + + if (i > 0) { + if (info->pFrame[(i * info->SenseChannelLength) + j] < *min) + *min = info->pFrame[(i * info->SenseChannelLength) + j]; + + if (info->pFrame[(i * info->SenseChannelLength) + j] > *max) + *max = info->pFrame[(i * info->SenseChannelLength) + j]; + } + strncat(pStr, pTmp, 6 * info->SenseChannelLength); + } + tsp_debug_info(&info->client->dev, "FTS %s\n", pStr); + } + + kfree(pStr); +} + +static int fts_panel_ito_test(struct fts_ts_info *info) +{ + unsigned char cmd = READ_ONE_EVENT; + unsigned char data[FTS_EVENT_SIZE]; + unsigned char regAdd[4] = {0xB0, 0x03, 0x60, 0xFB}; + unsigned char wregAdd[3] = {0xA7, 0x01, 0x00}; + uint8_t *errortypes[16] = { + "F open", "S open", "F2G short", "S2G short", "F2V short", + "S2V short", "F2F short", "S2S short", "F2S short", + "FPC F open", "FPC S open", "Key F open", "Key S open", + "Reserved", "Reserved", "Reserved"}; + int retry = 0; + int result = -1; + + info->fts_systemreset(info); + info->fts_wait_for_ready(info); + info->fts_irq_enable(info, false); + info->fts_interrupt_set(info, INT_DISABLE); + info->fts_write_reg(info, ®Add[0], 4); + info->fts_command(info, FLUSHBUFFER); + info->fts_write_reg(info, &wregAdd[0], 3); + fts_delay(200); + memset(data, 0x0, FTS_EVENT_SIZE); + while (info->fts_read_reg + (info, &cmd, 1, (unsigned char *)data, FTS_EVENT_SIZE)) { + if ((data[0] == 0x0F) && (data[1] == 0x05)) { + switch (data[2]) { + case NO_ERROR: + if (data[3] == 0x00) { + tsp_debug_info( + &info->client->dev, + "ITO open / short test PASS!!\n"); + return 1; + } + break; + case ITO_FORCE_OPEN: + case ITO_SENSE_OPEN: + case ITO_FORCE_SHRT_GND: + case ITO_SENSE_SHRT_GND: + case ITO_FORCE_SHRT_VCM: + case ITO_SENSE_SHRT_VCM: + case ITO_FORCE_SHRT_FORCE: + case ITO_SENSE_SHRT_SENSE: + case ITO_F2E_SENSE: + case ITO_FPC_FORCE_OPEN: + case ITO_FPC_SENSE_OPEN: + case ITO_KEY_FORCE_OPEN: + case ITO_KEY_SENSE_OPEN: + case ITO_RESERVED0: + case ITO_RESERVED1: + case ITO_RESERVED2: + case ITO_MAX_ERR_REACHED: + tsp_debug_info( + &info->client->dev, + "ITO open / short test FAIL!! Error Type : %s, Channel : %d\n", + errortypes[data[2]], data[3]); + break; + } + break; + } + if (retry++ > 30) { + tsp_debug_info(&info->client->dev, + "Time over - wait for result of ITO test\n"); + break; + } + fts_delay(10); + } + info->fts_systemreset(info); + info->fts_wait_for_ready(info); + info->fts_command(info, SENSEON); + info->touch_count = 0; + info->fts_command(info, FLUSHBUFFER); + info->fts_interrupt_set(info, INT_ENABLE); + info->fts_irq_enable(info, true); + return result; +} +int fts_read_frame(struct fts_ts_info *info, unsigned char type, short *min, + short *max) +{ + unsigned char pFrameAddress[8] = { + 0xD0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}; + unsigned int FrameAddress = 0; + unsigned int writeAddr = 0; + unsigned int start_addr = 0; + unsigned int end_addr = 0; + unsigned int totalbytes = 0; + unsigned int remained = 0; + unsigned int readbytes = 0xFF; + unsigned int dataposition = 0; + unsigned char *pRead = NULL; + int rc = 0; + int ret = 0; + int i = 0; + + tsp_debug_info(&info->client->dev, + "===> fts_read_frame digital rev( %d ) sense ( %d ) force (%d)\n", + info->digital_rev, info->SenseChannelLength, info->ForceChannelLength); + + pRead = kzalloc(BUFFER_MAX, GFP_KERNEL); + if (pRead == NULL) { + tsp_debug_info(&info->client->dev, + "FTS pRead kzalloc failed\n"); + rc = 1; + goto ErrorExit; + } + + pFrameAddress[2] = type; + totalbytes = info->SenseChannelLength * info->ForceChannelLength * 2; + ret = info->fts_read_reg(info, &pFrameAddress[0], 3, pRead, pFrameAddress[3]); + + if (ret > 0) { + if (info->digital_rev == FTS_DIGITAL_REV_1) + FrameAddress = pRead[0] + (pRead[1] << 8); + else if (info->digital_rev == FTS_DIGITAL_REV_2) + FrameAddress = pRead[1] + (pRead[2] << 8); + + start_addr = FrameAddress+info->SenseChannelLength * 2; + end_addr = start_addr + totalbytes; + } else { + tsp_debug_info(&info->client->dev, + "FTS read failed rc = %d\n", ret); + rc = 2; + goto ErrorExit; + } + +#ifdef DEBUG_MSG + tsp_debug_info(&info->client->dev, + "FTS FrameAddress = %X\n", FrameAddress); + tsp_debug_info(&info->client->dev, + "FTS start_addr = %X, end_addr = %X\n", + start_addr, end_addr); +#endif + + remained = totalbytes; + for (writeAddr = start_addr; writeAddr < end_addr; + writeAddr += READ_CHUNK_SIZE) { + pFrameAddress[1] = (writeAddr >> 8) & 0xFF; + pFrameAddress[2] = writeAddr & 0xFF; + + if (remained >= READ_CHUNK_SIZE) + readbytes = READ_CHUNK_SIZE; + else + readbytes = remained; + + memset(pRead, 0x0, readbytes); + +#ifdef DEBUG_MSG + tsp_debug_info(&info->client->dev, + "FTS %02X%02X%02X readbytes=%d\n", + pFrameAddress[0], pFrameAddress[1], + pFrameAddress[2], readbytes); + +#endif + if (info->digital_rev == FTS_DIGITAL_REV_1) { + info->fts_read_reg(info, &pFrameAddress[0], + 3, pRead, readbytes); + remained -= readbytes; + + for (i = 0; i < readbytes; i += 2) { + info->pFrame[dataposition++] = + pRead[i] + (pRead[i + 1] << 8); + } + } else if (info->digital_rev == FTS_DIGITAL_REV_2) { + info->fts_read_reg(info, &pFrameAddress[0], + 3, pRead, readbytes + 1); + remained -= readbytes; + + for (i = 1; i < (readbytes+1); i += 2) { + info->pFrame[dataposition++] = + pRead[i] + (pRead[i + 1] << 8); + } + } + } + kfree(pRead); + +#ifdef DEBUG_MSG + tsp_debug_info(&info->client->dev, + "FTS writeAddr = %X, start_addr = %X, end_addr = %X\n", + writeAddr, start_addr, end_addr); +#endif + + switch (type) { + case TYPE_RAW_DATA: + tsp_debug_info(&info->client->dev, + "FTS [Raw Data : 0x%X%X]\n", pFrameAddress[0], + FrameAddress); + break; + case TYPE_FILTERED_DATA: + tsp_debug_info(&info->client->dev, + "FTS [Filtered Data : 0x%X%X]\n", + pFrameAddress[0], FrameAddress); + break; + case TYPE_STRENGTH_DATA: + tsp_debug_info(&info->client->dev, + "FTS [Strength Data : 0x%X%X]\n", + pFrameAddress[0], FrameAddress); + break; + case TYPE_BASELINE_DATA: + tsp_debug_info(&info->client->dev, + "FTS [Baseline Data : 0x%X%X]\n", + pFrameAddress[0], FrameAddress); + break; + } + fts_print_frame(info, min, max); + +ErrorExit: + return rc; +} + +static void get_fw_ver_bin(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[16] = {0}; + + set_default_result(info); + + if (strncmp(info->board->model_name, "G925", 4) == 0) { + info->tspid_val = gpio_get_value(info->board->tspid); + info->tspid2_val = gpio_get_value(info->board->tspid2); + + sprintf(buff, "ST%01X%01X%04X", + info->tspid_val, info->tspid2_val, + info->fw_main_version_of_bin); + } else { + sprintf(buff, "ST%02X%04X", + info->panel_revision, + info->fw_main_version_of_bin); + } + + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void get_fw_ver_ic(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[16] = {0}; + + set_default_result(info); + + if (strncmp(info->board->model_name, "G925", 4) == 0) { + info->tspid_val = gpio_get_value(info->board->tspid); + info->tspid2_val = gpio_get_value(info->board->tspid2); + + sprintf(buff, "ST%01X%01X%04X", + info->tspid_val, info->tspid2_val, + info->fw_main_version_of_ic); + } else { + sprintf(buff, "ST%02X%04X", + info->panel_revision, + info->fw_main_version_of_ic); + } + + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void get_config_ver(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[20] = {0}; + const char *name = NULL; + + if (info->board->model_name) + name = info->board->model_name; + else if (info->board->project_name) + name = info->board->project_name; + + snprintf(buff, sizeof(buff), "%s_ST_%04X", + name? name : STM_DEVICE_NAME, + info->config_version_of_ic); + + set_default_result(info); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void get_threshold(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + unsigned char cmd[4] = {0xB2, 0x00, 0x62, 0x02}; + char buff[CMD_STR_LEN] = {0}; + int timeout = 0; + + set_default_result(info); + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + info->fts_write_reg(info, &cmd[0], 4); + info->cmd_state = CMD_STATUS_RUNNING; + + while (info->cmd_state == CMD_STATUS_RUNNING) { + if (timeout++ > 30) { + info->cmd_state = CMD_STATUS_FAIL; + break; + } + fts_delay(10); + } +} + +static void get_x_num(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[16] = { 0 }; + + set_default_result(info); + snprintf(buff, sizeof(buff), "%d", info->SenseChannelLength); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = 2; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void get_y_num(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[16] = { 0 }; + + set_default_result(info); + snprintf(buff, sizeof(buff), "%d", info->ForceChannelLength); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void run_rawcap_read(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + short min = 0x7FFF; + short max = 0x8000; + + set_default_result(info); + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max); + snprintf(buff, sizeof(buff), "%d,%d", min, max); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); + +} + +static void get_rawcap(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + short val = 0; + int node = 0; + + set_default_result(info); + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + node = fts_check_index(info); + if (node < 0) + return; + + val = info->pFrame[node]; + snprintf(buff, sizeof(buff), "%d", val); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void get_strength_all_data(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + short min = 0x7FFF; + short max = 0x8000; + const int str_size = info->ForceChannelLength * + info->SenseChannelLength * 5; + char all_strbuff[str_size]; + int i, j; + + memset(all_strbuff, 0, sizeof(char)*(str_size)); /* size 5 ex(1125,) */ + + set_default_result(info); + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max); + + + for (i = 0; i < info->ForceChannelLength; i++) { + for (j = 0; j < info->SenseChannelLength; j++) { + sprintf(buff, "%d,", + info->pFrame[ + (i * info->SenseChannelLength) + j]); + strcat(all_strbuff, buff); + } + } + + info->cmd_state = CMD_STATUS_OK; + + set_cmd_result(info, all_strbuff, + strnlen(all_strbuff, sizeof(all_strbuff))); + tsp_debug_info(&info->client->dev, + "%ld (%ld)\n", strnlen(all_strbuff, + sizeof(all_strbuff)), sizeof(all_strbuff)); +} + +void fts_read_self_frame(struct fts_ts_info *info, unsigned short oAddr) +{ + char buff[66] = {0, }; + short *data = 0; + char temp[9] = {0, }; + char temp2[512] = {0, }; + int i = 0; + int rc = 0; + unsigned char regAdd[6] = {0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00}; + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + regAdd[1] = (oAddr >> 8) & 0xff; + regAdd[2] = oAddr & 0xff; + rc = info->fts_read_reg(info, ®Add[0], 3, (unsigned char *)&buff[0], 5); + if (rc < 0) { + info->cmd_state = CMD_STATUS_FAIL; + return; + } + + if (info->digital_rev == FTS_DIGITAL_REV_1) { + tsp_debug_info(&info->client->dev, + "%s: Force Address : %02x%02x\n", + __func__, buff[1], buff[0]); + tsp_debug_info(&info->client->dev, + "%s: Sense Address : %02x%02x\n", + __func__, buff[3], buff[2]); + regAdd[1] = buff[3]; + regAdd[2] = buff[2]; + regAdd[4] = buff[1]; + regAdd[5] = buff[0]; + } else if (info->digital_rev == FTS_DIGITAL_REV_2) { + tsp_debug_info(&info->client->dev, + "%s: Force Address : %02x%02x\n", + __func__, buff[2], buff[1]); + tsp_debug_info(&info->client->dev, + "%s: Sense Address : %02x%02x\n", + __func__, buff[4], buff[3]); + regAdd[1] = buff[4]; + regAdd[2] = buff[3]; + regAdd[4] = buff[2]; + regAdd[5] = buff[1]; + } + + rc = info->fts_read_reg(info, ®Add[0], 3, + (unsigned char *)&buff[0], + info->SenseChannelLength * 2 + 1); + if (rc < 0) { + info->cmd_state = CMD_STATUS_FAIL; + return; + } + + if (info->digital_rev == FTS_DIGITAL_REV_1) + data = (short *)&buff[0]; + else + data = (short *)&buff[1]; + + memset(temp, 0x00, ARRAY_SIZE(temp)); + memset(temp2, 0x00, ARRAY_SIZE(temp2)); + + for (i = 0; i < info->SenseChannelLength; i++) { + tsp_debug_info(&info->client->dev, + "%s: Rx [%d] = %d\n", __func__, + i, + *data); + sprintf(temp, "%d,", *data); + strncat(temp2, temp, 9); + data++; + } + + rc = info->fts_read_reg(info, ®Add[3], 3, + (unsigned char *)&buff[0], + info->ForceChannelLength * 2 + 1); + if (rc < 0) { + info->cmd_state = CMD_STATUS_FAIL; + return; + } + + if (info->digital_rev == FTS_DIGITAL_REV_1) + data = (short *)&buff[0]; + else + data = (short *)&buff[1]; + + for (i = 0; i < info->ForceChannelLength; i++) { + tsp_debug_info(&info->client->dev, + "%s: Tx [%d] = %d\n", __func__, i, *data); + sprintf(temp, "%d,", *data); + strncat(temp2, temp, 9); + data++; + } + + set_cmd_result(info, temp2, strnlen(temp2, sizeof(temp2))); + + info->cmd_state = CMD_STATUS_OK; +} + +static void fts_read_ix_data(struct fts_ts_info *info, bool allnode) +{ + char buff[33] = { 0 }; + + unsigned short max_tx_ix_sum = 0; + unsigned short min_tx_ix_sum = 0xFFFF; + + unsigned short max_rx_ix_sum = 0; + unsigned short min_rx_ix_sum = 0xFFFF; + + unsigned char tx_ix2[info->ForceChannelLength + 4]; + unsigned char rx_ix2[info->SenseChannelLength + 4]; + + unsigned char regAdd[FTS_EVENT_SIZE]; + unsigned short tx_ix1 = 0, rx_ix1 = 0; + + unsigned short force_ix_data[info->ForceChannelLength * 2 + 1]; + unsigned short sense_ix_data[info->SenseChannelLength * 2 + 1]; + int buff_size, j; + char *mbuff = NULL; + int num, n, a, fzero; + char cnum; + int i = 0; + int comp_header_addr, comp_start_tx_addr, comp_start_rx_addr; + unsigned int rx_num, tx_num; + + set_default_result(info); + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + info->fts_irq_enable(info, false); + info->fts_interrupt_set(info, INT_DISABLE); + + info->fts_command(info, SENSEOFF); + + info->fts_command(info, FLUSHBUFFER); /* Clear FIFO */ + fts_delay(50); + + info->fts_release_all_finger(info); + + /* Request compensation data */ + regAdd[0] = 0xB8; + regAdd[1] = 0x20; /* SELF IX */ + regAdd[2] = 0x00; + info->fts_write_reg(info, ®Add[0], 3); + fts_fw_wait_for_specific_event(info, + EVENTID_STATUS_REQUEST_COMP, 0x20, 0x00); + + /* Read an address of compensation data */ + regAdd[0] = 0xD0; + regAdd[1] = 0x00; + regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR; + info->fts_read_reg(info, regAdd, 3, &buff[0], 3); + comp_header_addr = buff[1] + (buff[2] << 8); + + /* Read header of compensation area */ + regAdd[0] = 0xD0; + regAdd[1] = (comp_header_addr >> 8) & 0xFF; + regAdd[2] = comp_header_addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1); + tx_num = buff[5]; + rx_num = buff[6]; + tsp_debug_info(&info->client->dev, + "%s: [FTS] tx : %d, rx : %d", + __func__, tx_num, rx_num); + + tx_ix1 = (short) buff[10]; + rx_ix1 = (short) buff[11]; + + comp_start_tx_addr = comp_header_addr + 0x10; + comp_start_rx_addr = comp_start_tx_addr + tx_num; + + memset(tx_ix2, 0x0, tx_num); + memset(rx_ix2, 0x0, rx_num); + + /* Read Self TX Ix2 */ + regAdd[0] = 0xD0; + regAdd[1] = (comp_start_tx_addr >> 8) & 0xFF; + regAdd[2] = comp_start_tx_addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &tx_ix2[0], tx_num + 1); + + /* Read Self RX Ix2 */ + regAdd[0] = 0xD0; + regAdd[1] = (comp_start_rx_addr >> 8) & 0xFF; + regAdd[2] = comp_start_rx_addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &rx_ix2[0], rx_num + 1); + + for (i = 0; i < info->ForceChannelLength; i++) { + force_ix_data[i] = tx_ix1 + tx_ix2[i + 1]; + if (max_tx_ix_sum < force_ix_data[i]) + max_tx_ix_sum = force_ix_data[i]; + if (min_tx_ix_sum > force_ix_data[i]) + min_tx_ix_sum = force_ix_data[i]; + } + + for (i = 0; i < info->SenseChannelLength; i++) { + sense_ix_data[i] = rx_ix1 + rx_ix2[i + 1]; + if (max_rx_ix_sum < sense_ix_data[i]) + max_rx_ix_sum = sense_ix_data[i]; + if (min_rx_ix_sum > sense_ix_data[i]) + min_rx_ix_sum = sense_ix_data[i]; + } + + tsp_debug_info(&info->client->dev, + "%s: MIN_TX_IX_SUM : %d MAX_TX_IX_SUM : %d\n", + __func__, min_tx_ix_sum, max_tx_ix_sum); + tsp_debug_info(&info->client->dev, + "%s: MIN_RX_IX_SUM : %d MAX_RX_IX_SUM : %d\n", + __func__, min_rx_ix_sum, max_rx_ix_sum); + + info->fts_command(info, SENSEON); + + info->fts_irq_enable(info, true); + info->fts_interrupt_set(info, INT_ENABLE); + + if (allnode == true) { + buff_size = (info->ForceChannelLength + + info->SenseChannelLength + 2) * 5; + mbuff = kzalloc(buff_size, GFP_KERNEL); + } + if (mbuff != NULL) { + char *pBuf = mbuff; + + for (i = 0; i < info->ForceChannelLength; i++) { + num = force_ix_data[i]; + n = 100000; + fzero = 0; + for (j = 5; j > 0; j--) { + n = n / 10; + a = num / n; + if (a) + fzero = 1; + cnum = a + '0'; + num = num - a*n; + if (fzero) + *pBuf++ = cnum; + } + if (!fzero) + *pBuf++ = '0'; + *pBuf++ = ','; + tsp_debug_info(&info->client->dev, + "Force[%d] %d\n", i, force_ix_data[i]); + } + for (i = 0; i < info->SenseChannelLength; i++) { + num = sense_ix_data[i]; + n = 100000; + fzero = 0; + for (j = 5; j > 0; j--) { + n = n / 10; + a = num / n; + if (a) + fzero = 1; + cnum = a + '0'; + num = num - a * n; + if (fzero) + *pBuf++ = cnum; + } + if (!fzero) + *pBuf++ = '0'; + if (i < (info->SenseChannelLength - 1)) + *pBuf++ = ','; + tsp_debug_info(&info->client->dev, + "Sense[%d] %d\n", i, sense_ix_data[i]); + } + + set_cmd_result(info, mbuff, buff_size); + info->cmd_state = CMD_STATUS_OK; + kfree(mbuff); + } else { + if (allnode == true) { + snprintf(buff, sizeof(buff), "%s", "kzalloc failed"); + info->cmd_state = CMD_STATUS_FAIL; + } else{ + snprintf(buff, sizeof(buff), "%d,%d,%d,%d", + min_tx_ix_sum, max_tx_ix_sum, + min_rx_ix_sum, max_rx_ix_sum); + info->cmd_state = CMD_STATUS_OK; + } + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + tsp_debug_info(&info->client->dev, + "%s: %s\n", __func__, buff); + } +} + +static void run_ix_data_read(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + + set_default_result(info); + fts_read_ix_data(info, false); +} + +static void run_ix_data_read_all(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + + set_default_result(info); + fts_read_ix_data(info, true); +} + +static void fts_read_self_raw_frame(struct fts_ts_info *info, + unsigned short oAddr, bool allnode) +{ + char buff[32 * 2 + 1] = { 0 }; + unsigned char D0_offset = 1; + unsigned char regAdd[3] = {0xD0, 0x00, 0x00}; + unsigned char ReadData[info->SenseChannelLength * 2 + 1]; + unsigned short self_force_raw_data[info->ForceChannelLength * 2 + 1]; + unsigned short self_sense_raw_data[info->SenseChannelLength * 2 + 1]; + unsigned int FrameAddress = 0; + unsigned char count = 0; + int buff_size, i, j; + char *mbuff = NULL; + int num, n, a, fzero; + char cnum; + unsigned short min_tx_self_raw_data = 0xFFFF; + unsigned short max_tx_self_raw_data = 0; + unsigned short min_rx_self_raw_data = 0xFFFF; + unsigned short max_rx_self_raw_data = 0; + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + info->fts_irq_enable(info, false); + info->fts_interrupt_set(info, INT_DISABLE); + info->fts_command(info, SENSEOFF); + + fts_delay(50); + + info->fts_command(info, FLUSHBUFFER); /* Clear FIFO */ + fts_delay(50); + + regAdd[1] = 0x00; + regAdd[2] = oAddr; + info->fts_read_reg(info, regAdd, 3, &ReadData[0], 4); + + /* D1 : DOFFSET = 0, D2 : DOFFSET : 1 */ + FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); + + regAdd[1] = (FrameAddress >> 8) & 0xFF; + regAdd[2] = FrameAddress & 0xFF; + + info->fts_read_reg(info, regAdd, 3, &ReadData[0], info->ForceChannelLength * 2 + 1); + + for (count = 0; count < info->ForceChannelLength; count++) { + self_force_raw_data[count] = ReadData[count*2+D0_offset] + (ReadData[count*2+D0_offset+1]<<8); + + if (max_tx_self_raw_data < self_force_raw_data[count]) + max_tx_self_raw_data = self_force_raw_data[count]; + if (min_tx_self_raw_data > self_force_raw_data[count]) + min_tx_self_raw_data = self_force_raw_data[count]; + } + + regAdd[1] = 0x00; + regAdd[2] = oAddr + 2; + info->fts_read_reg(info, regAdd, 3, &ReadData[0], 4); + + FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); /* D1 : DOFFSET = 0, D2 : DOFFSET : 1 */ + + regAdd[1] = (FrameAddress >> 8) & 0xFF; + regAdd[2] = FrameAddress & 0xFF; + + info->fts_read_reg(info, regAdd, 3, &ReadData[0], + info->SenseChannelLength * 2 + 1); + + for (count = 0; count < info->SenseChannelLength; count++) { + self_sense_raw_data[count] = ReadData[count*2+D0_offset] + + (ReadData[count*2+D0_offset+1]<<8); + + if (max_rx_self_raw_data < self_sense_raw_data[count]) + max_rx_self_raw_data = self_sense_raw_data[count]; + if (min_rx_self_raw_data > self_sense_raw_data[count]) + min_rx_self_raw_data = self_sense_raw_data[count]; + } + + tsp_debug_info(&info->client->dev, + "%s MIN_TX_SELF_RAW: %d MAX_TX_SELF_RAW : %d\n", + __func__, min_tx_self_raw_data, max_tx_self_raw_data); + tsp_debug_info(&info->client->dev, + "%s MIN_RX_SELF_RAW : %d MIN_RX_SELF_RAW : %d\n", + __func__, min_rx_self_raw_data, max_rx_self_raw_data); + + fts_delay(1); + info->fts_command(info, SENSEON); + + info->fts_irq_enable(info, true); + info->fts_interrupt_set(info, INT_ENABLE); + + if (allnode == true) { + buff_size = (info->ForceChannelLength + + info->SenseChannelLength + 2)*10; + mbuff = kzalloc(buff_size, GFP_KERNEL); + } + if (mbuff != NULL) { + char *pBuf = mbuff; + + for (i = 0; i < info->ForceChannelLength; i++) { + num = self_force_raw_data[i]; + n = 100000; + fzero = 0; + for (j = 5; j > 0; j--) { + n = n/10; + a = num/n; + if (a) + fzero = 1; + cnum = a + '0'; + num = num - a*n; + if (fzero) + *pBuf++ = cnum; + } + if (!fzero) + *pBuf++ = '0'; + *pBuf++ = ','; + tsp_debug_info(&info->client->dev, "%d ", self_force_raw_data[i]); + } + for (i = 0; i < info->SenseChannelLength; i++) { + num = self_sense_raw_data[i]; + n = 100000; + fzero = 0; + for (j = 5; j > 0; j--) { + n = n/10; + a = num/n; + if (a) + fzero = 1; + cnum = a + '0'; + num = num - a*n; + if (fzero) + *pBuf++ = cnum; + } + if (!fzero) + *pBuf++ = '0'; + if (i < (info->SenseChannelLength-1)) + *pBuf++ = ','; + tsp_debug_info(&info->client->dev, "%d ", self_sense_raw_data[i]); + } + + + set_cmd_result(info, mbuff, buff_size); + info->cmd_state = CMD_STATUS_OK; + kfree(mbuff); + } else { + if (allnode == true) { + snprintf(buff, sizeof(buff), "%s", "kzalloc failed"); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + } else{ + snprintf(buff, sizeof(buff), "%d,%d,%d,%d", + min_tx_self_raw_data, + max_tx_self_raw_data, + min_rx_self_raw_data, + max_rx_self_raw_data); + info->cmd_state = CMD_STATUS_OK; + } + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + tsp_debug_info(&info->client->dev, "%s: %s\n", + __func__, buff); + } +} + +static void run_self_raw_read(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + + set_default_result(info); + fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR, false); +} + +static void run_self_raw_read_all(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + + set_default_result(info); + fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR, true); +} + +static void get_cx_data(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + short val = 0; + int node = 0; + + set_default_result(info); + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + node = fts_check_index(info); + if (node < 0) + return; + + val = info->cx_data[node]; + snprintf(buff, sizeof(buff), "%d", val); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_OK; + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); + +} + +static void run_cx_data_read(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + + char buff[SEC_CMD_STR_LEN] = { 0 }; + unsigned char ReadData[info->ForceChannelLength] + [info->SenseChannelLength + FTS_CX2_READ_LENGTH]; + int cxdiffData_rx[info->ForceChannelLength * + (info->SenseChannelLength + FTS_CX2_READ_LENGTH)]; + int cxdiffData_tx[info->ForceChannelLength * + (info->SenseChannelLength + FTS_CX2_READ_LENGTH)]; + int Max_cxdiffData_rx = 0; + int Low_cxdiffData_rx = 0; + int Max_cxdiffData_tx = 0; + int Low_cxdiffData_tx = 0; + unsigned char regAdd[8]; + unsigned int addr, rx_num, tx_num; + int i, j; + unsigned char *pStr = NULL; + unsigned char pTmp[16] = { 0 }; + + int comp_header_addr, comp_start_addr; + + set_default_result(info); + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL); + if (pStr == NULL) { + tsp_debug_info(&info->client->dev, + "%s: pStr kzalloc failed\n", __func__); + return; + } + + tsp_debug_info(&info->client->dev, "%s: start\n", __func__); + + info->fts_irq_enable(info, false); + tsp_debug_info(&info->client->dev, "%s: disable_irq\n", __func__); + info->fts_interrupt_set(info, INT_DISABLE); + tsp_debug_info(&info->client->dev, + "%s: fts_interrupt_set\n", __func__); + info->fts_command(info, SENSEOFF); + tsp_debug_info(&info->client->dev, "%s: fts_command\n", __func__); + fts_delay(50); + tsp_debug_info(&info->client->dev, "%s: senseoff\n", __func__); + + info->fts_command(info, FLUSHBUFFER); + fts_delay(50); + + info->fts_release_all_finger(info); + + /* Request compensation data */ + regAdd[0] = 0xB8; + regAdd[1] = 0x04; /* MUTUAL CX (LPA) */ + regAdd[2] = 0x00; + info->fts_write_reg(info, ®Add[0], 3); + tsp_debug_info(&info->client->dev, + "%s: Writing Request compensation data\n", __func__); + fts_cmd_completion_check(info, EVENTID_STATUS_REQUEST_COMP, + regAdd[1], regAdd[2]); + + /* Read an address of compensation data */ + regAdd[0] = 0xD0; + regAdd[1] = 0x00; + regAdd[2] = 0x50; + info->fts_read_reg(info, regAdd, 3, &buff[0], 4); + comp_header_addr = buff[1] + (buff[2] << 8); + tsp_debug_info(&info->client->dev, + "%s:Read an address of compensation data\n", __func__); + + /* Read header of compensation area */ + regAdd[0] = 0xD0; + regAdd[1] = (comp_header_addr >> 8) & 0xFF; + regAdd[2] = comp_header_addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1); + tx_num = buff[5]; + rx_num = buff[6]; + comp_start_addr = comp_header_addr + 0x10; + + tsp_debug_info(&info->client->dev, + "%s:Read header of compensation area data\n", __func__); + tsp_debug_info(&info->client->dev, + "%s: Tx num ( %d ) Rx num ( %d )\n", __func__, + tx_num, rx_num); + tsp_debug_info(&info->client->dev, + "%s: comp_stat_addr : 0x%x\n", __func__, + comp_start_addr); + /* Read compensation data */ + for (j = 0; j < tx_num; j++) { + memset(&ReadData[j], 0x0, rx_num); + memset(pStr, 0x0, 4 * (rx_num + 1)); + snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j); + strncat(pStr, pTmp, 4 * rx_num); + + addr = comp_start_addr + (rx_num * j); + regAdd[0] = 0xD0; + regAdd[1] = (addr >> 8) & 0xFF; + regAdd[2] = addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1); + for (i = 1; i < rx_num + 1; i++) { + snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i]); + strncat(pStr, pTmp, 4 * rx_num); + } + tsp_debug_info(&info->client->dev, "%s\n", pStr); + } + + tsp_debug_info(&info->client->dev, + "%s:Read compensation data\n", __func__); + if (info->cx_data) { + for (j = 0; j < tx_num; j++) { + for (i = 1; i < rx_num + 1; i++) + info->cx_data[(j * rx_num) + i - 1] = + ReadData[j][i]; + } + } + tsp_debug_err(&info->client->dev, + "===================> %s : Rx diff\n", __func__); + for (j = 0; j < tx_num; j++) { + memset(pStr, 0x0, 4 * (rx_num + 1)); + snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j); + strncat(pStr, pTmp, 16); + for (i = 0; i < (rx_num-1); i++) { + cxdiffData_rx[(j*rx_num)+i] = + info->cx_data[(j*rx_num)+i] - + info->cx_data[(j*rx_num)+i+1]; + if ((j == 0) && (i == 0)) { + Max_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i]; + Low_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i]; + } + if (cxdiffData_rx[(j*rx_num)+i] > Max_cxdiffData_rx) + Max_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i]; + if (cxdiffData_rx[(j*rx_num)+i] < Low_cxdiffData_rx) + Low_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i]; + snprintf(pTmp, sizeof(pTmp), "%4d", cxdiffData_rx[(j*rx_num)+i]); + strcat(pStr, pTmp); + } + tsp_debug_info(&info->client->dev, "FTS %s\n", pStr); + } + tsp_debug_err(&info->client->dev, + "======> Max : %d / Low : %d <=========\n", + Max_cxdiffData_rx, Low_cxdiffData_rx); + tsp_debug_err(&info->client->dev, + " %s : Tx diff\n <=======================", __func__); + for (j = 0; j < (tx_num - 1); j++) { + memset(pStr, 0x0, 4 * (rx_num + 1)); + snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j); + strncat(pStr, pTmp, 16); + for (i = 0; i < rx_num; i++) { + cxdiffData_tx[(j*rx_num)+i] = + info->cx_data[(j*rx_num)+i] - + info->cx_data[((j+1)*rx_num)+i]; + if ((j == 0) && (i == 0)) { + Max_cxdiffData_tx = cxdiffData_rx[(j*rx_num)+i]; + Low_cxdiffData_tx = cxdiffData_rx[(j*rx_num)+i]; + } + if (cxdiffData_tx[(j*rx_num)+i] > Max_cxdiffData_tx) + Max_cxdiffData_tx = cxdiffData_tx[(j*rx_num)+i]; + if (cxdiffData_tx[(j*rx_num)+i] < Low_cxdiffData_tx) + Low_cxdiffData_tx = cxdiffData_tx[(j*rx_num)+i]; + snprintf(pTmp, sizeof(pTmp), "%4d", + cxdiffData_tx[(j*rx_num)+i]); + strcat(pStr, pTmp); + } + tsp_debug_info(&info->client->dev, "FTS %s\n", pStr); + } + tsp_debug_err(&info->client->dev, + "======> Max : %d / Low : %d <=========\n", + Max_cxdiffData_tx, Low_cxdiffData_tx); + + kfree(pStr); + + snprintf(buff, sizeof(buff), "%s", "OK"); + info->fts_irq_enable(info, true); + info->fts_interrupt_set(info, INT_ENABLE); + info->fts_command(info, SENSEON); + info->cmd_state = CMD_STATUS_OK; + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); + +} + +static void get_cx_all_data(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[SEC_CMD_STR_LEN] = { 0 }; + unsigned char ReadData[info->ForceChannelLength] + [info->SenseChannelLength + FTS_CX2_READ_LENGTH]; + unsigned char regAdd[8]; + unsigned int addr, rx_num, tx_num; + int i, j; + unsigned char *pStr = NULL; + unsigned char pTmp[16] = { 0 }; + char all_strbuff[(info->ForceChannelLength)* + (info->SenseChannelLength)*3]; + + int comp_header_addr, comp_start_addr; + + set_default_result(info); + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + tsp_debug_info(&info->client->dev, "%s: start\n", __func__); + + info->fts_command(info, SENSEOFF); + info->fts_irq_enable(info, false); + info->fts_command(info, FLUSHBUFFER); + fts_delay(50); + + info->fts_release_all_finger(info); + + tx_num = info->ForceChannelLength; + rx_num = info->SenseChannelLength; + + pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL); + if (pStr == NULL) { + tsp_debug_info(&info->client->dev, + "%s: pStr kzalloc failed\n", __func__); + goto out; + } + + /* size 3 ex(45,) */ + memset(all_strbuff, 0, sizeof(char) * (tx_num*rx_num*3)); + + /* Request compensation data */ + regAdd[0] = 0xB8; + regAdd[1] = 0x04; /* MUTUAL CX (LPA) */ + regAdd[2] = 0x00; + info->fts_write_reg(info, ®Add[0], 3); + fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, 0x04, 0x00); + + /* Read an address of compensation data */ + regAdd[0] = 0xD0; + regAdd[1] = 0x00; + regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR; + info->fts_read_reg(info, regAdd, 3, &buff[0], 4); + comp_header_addr = buff[1] + (buff[2] << 8); + + /* Read header of compensation area */ + regAdd[0] = 0xD0; + regAdd[1] = (comp_header_addr >> 8) & 0xFF; + regAdd[2] = comp_header_addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1); + tx_num = buff[5]; + rx_num = buff[6]; + comp_start_addr = comp_header_addr + 0x10; + + /* Read compensation data */ + for (j = 0; j < tx_num; j++) { + memset(&ReadData[j], 0x0, rx_num); + memset(pStr, 0x0, 4 * (rx_num + 1)); + snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j); + strlcat(pStr, pTmp, 4 * (rx_num + 1)); + + addr = comp_start_addr + (rx_num * j); + regAdd[0] = 0xD0; + regAdd[1] = (addr >> 8) & 0xFF; + regAdd[2] = addr & 0xFF; + info->fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1); + for (i = 0; i < rx_num; i++) { + snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i]); + strlcat(pStr, pTmp, 4 * (rx_num + 1)); + } + tsp_debug_info(&info->client->dev, "%s\n", pStr); + } + + if (info->cx_data) { + for (j = 0; j < tx_num; j++) { + for (i = 0; i < rx_num; i++) { + info->cx_data[(j * rx_num) + i] = + ReadData[j][i]; + snprintf(buff, sizeof(buff), + "%d,", ReadData[j][i]); + strlcat(all_strbuff, buff, sizeof(all_strbuff)); + } + } + } + + kfree(pStr); + +out: + info->fts_irq_enable(info, true); + info->fts_command(info, SENSEON); + info->cmd_state = CMD_STATUS_OK; + set_cmd_result(info, all_strbuff, + strnlen(all_strbuff, sizeof(all_strbuff))); + tsp_debug_info(&info->client->dev, + "%s: %ld (%ld)\n", __func__, + strnlen(all_strbuff, sizeof(all_strbuff)), + sizeof(all_strbuff)); +} + + +static void set_tsp_test_result(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + unsigned char regAdd[4] = {0xB0, 0x07, 0xE7, 0x00}; + + set_default_result(info); + + if (info->cmd_param[0] < TSP_FACTEST_RESULT_NONE + || info->cmd_param[0] > TSP_FACTEST_RESULT_PASS) { + snprintf(buff, sizeof(buff), "%s", "NG"); + info->cmd_state = CMD_STATUS_FAIL; + return; + } + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + info->fts_irq_enable(info, false); + info->fts_interrupt_set(info, INT_DISABLE); + + regAdd[3] = info->cmd_param[0]; + info->fts_write_reg(info, ®Add[0], 4); + fts_delay(100); + info->fts_command(info, FTS_CMD_SAVE_FWCONFIG); + + fts_delay(230); + fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CONFIG, 0x00); + + info->fts_irq_enable(info, true); + info->fts_interrupt_set(info, INT_ENABLE); + + snprintf(buff, sizeof(buff), "%s", "OK"); + info->cmd_state = CMD_STATUS_OK; + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void get_tsp_test_result(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + unsigned char cmd[4] = {0xB2, 0x07, 0xE7, 0x01}; + char buff[CMD_STR_LEN] = { 0 }; + int timeout = 0; + + set_default_result(info); + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + info->fts_command(info, FLUSHBUFFER); + info->fts_write_reg(info, &cmd[0], 4); + info->cmd_state = CMD_STATUS_RUNNING; + + while (info->cmd_state == CMD_STATUS_RUNNING) { + if (timeout++ > 30) { + info->cmd_state = CMD_STATUS_FAIL; + break; + } + fts_delay(10); + } +} + +static void run_trx_short_test(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + int ret = 0; + + set_default_result(info); + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + info->fts_irq_enable(info, false); + ret = fts_panel_ito_test(info); + if (ret == 1) + snprintf(buff, sizeof(buff), "%s", "OK"); + else + snprintf(buff, sizeof(buff), "%s", "FAIL"); + info->fts_irq_enable(info, true); + info->cmd_state = CMD_STATUS_OK; + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void report_rate(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + + set_default_result(info); + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + goto out; + } + + if (info->cmd_param[0] < 0 || info->cmd_param[0] > 2) { + snprintf(buff, sizeof(buff), "%s", "NG"); + info->cmd_state = CMD_STATUS_FAIL; + } else { + snprintf(buff, sizeof(buff), "%s", "OK"); + info->cmd_state = CMD_STATUS_OK; + } + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_WAITING; + +out: + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void delay(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + + set_default_result(info); + + info->delay_time = info->cmd_param[0]; + + tsp_debug_info(&info->client->dev, + "%s: delay time is %d\n", __func__, info->delay_time); + snprintf(buff, sizeof(buff), "%d", info->delay_time); + + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + info->cmd_state = CMD_STATUS_WAITING; + + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void debug(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + + set_default_result(info); + + info->debug_string = info->cmd_param[0]; + + tsp_debug_info(&info->client->dev, + "%s: command is %d\n", __func__, info->debug_string); + + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + info->cmd_state = CMD_STATUS_WAITING; + + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void run_autotune_enable(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + + set_default_result(info); + + info->run_autotune = info->cmd_param[0]; + + tsp_debug_info(&info->client->dev, "%s: command is %s\n", + __func__, info->run_autotune ? "ENABLE" : "DISABLE"); + + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + info->cmd_state = CMD_STATUS_WAITING; + + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); +} + +static void run_autotune(void *device_data) +{ + struct fts_ts_info *info = (struct fts_ts_info *)device_data; + char buff[CMD_STR_LEN] = { 0 }; + + set_default_result(info); + + if (info->touch_stopped) { + dev_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", __func__); + } + + if (info->touch_stopped) { + tsp_debug_info(&info->client->dev, + "%s: [ERROR] Touch is stopped\n", + __func__); + snprintf(buff, sizeof(buff), "%s", "TSP turned off"); + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + info->cmd_state = CMD_STATUS_NOT_APPLICABLE; + return; + } + + if (!info->run_autotune) { + tsp_debug_info(&info->client->dev, + "%s: autotune is disabled, %d\n", + __func__, info->run_autotune); + goto autotune_fail; + } + + info->fts_irq_enable(info, false); + + if (info->digital_rev == FTS_DIGITAL_REV_2) { + info->fts_interrupt_set(info, INT_DISABLE); + + info->fts_command(info, SENSEOFF); + fts_delay(50); + + info->fts_command(info, FTS_CMD_TRIM_LOW_POWER_OSCILLATOR); + fts_delay(200); + + info->fts_command(info, FLUSHBUFFER); + + info->fts_release_all_finger(info); + fts_execute_autotune(info); + + info->fts_command(info, SENSEON); + + info->fts_interrupt_set(info, INT_ENABLE); + } else { + tsp_debug_info(&info->client->dev, + "%s: digital_rev not matched, %d\n", + __func__, info->digital_rev); + goto autotune_fail; + } + + info->fts_irq_enable(info, true); + snprintf(buff, sizeof(buff), "%s", "OK"); + info->cmd_state = CMD_STATUS_OK; + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); + return; + +autotune_fail: + snprintf(buff, sizeof(buff), "%s", "NG"); + info->cmd_state = CMD_STATUS_FAIL; + set_cmd_result(info, buff, strnlen(buff, sizeof(buff))); + + mutex_lock(&info->cmd_lock); + info->cmd_is_running = false; + mutex_unlock(&info->cmd_lock); + + tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff); + return; +} + +void fts_production_init(void *device_info) +{ + char pdc_dir_name[20] = {0, }; + int j = 0; + struct fts_ts_info *info = (struct fts_ts_info *)device_info; + int retval = 0; + + INIT_LIST_HEAD(&info->cmd_list_head); + + info->cmd_buf_size = 0; + for (j = 0; j < ARRAY_SIZE(fts_commands); j++) { + list_add_tail(&fts_commands[j].list, &info->cmd_list_head); + if (fts_commands[j].cmd_name) + info->cmd_buf_size += strlen(fts_commands[j].cmd_name) + 1; + } + + mutex_init(&info->cmd_lock); + info->cmd_is_running = false; + + sprintf(pdc_dir_name, "ftm4_touch"); + + info->pdc_dev_ts = device_create(info->input_dev->dev.class, + NULL, 0, NULL, pdc_dir_name); + if (IS_ERR(info->pdc_dev_ts)) { + tsp_debug_err(&info->client->dev, + "FTS Failed to create device for the sysfs\n"); + retval = -ENOENT; + goto err_sysfs; + } + + dev_set_drvdata(info->pdc_dev_ts, info); + + retval = sysfs_create_group(&info->pdc_dev_ts->kobj, + &touch_pdc_attr_group); + if (retval < 0) { + tsp_debug_err(&info->client->dev, + "FTS Failed to create sysfs group\n"); + goto err_sysfs; + } + + + if (retval < 0) { + tsp_debug_err(&info->client->dev, + "%s: Failed to create link\n", __func__); + goto err_sysfs; + } + + return; +err_sysfs: + mutex_destroy(&info->cmd_lock); +} +EXPORT_SYMBOL(fts_production_init); diff --git a/drivers/input/touchscreen/stm/ftm4_ts.c b/drivers/input/touchscreen/stm/ftm4_ts.c new file mode 100644 index 000000000000..d5a9f948d1ae --- /dev/null +++ b/drivers/input/touchscreen/stm/ftm4_ts.c @@ -0,0 +1,2277 @@ +/******************** (C) COPYRIGHT 2012 STMicroelectronics ******************** +* +* File Name : fts.c +* Authors : AMS(Analog Mems Sensor) Team +* Description : FTS Capacitive touch screen controller (FingerTipS) +* +******************************************************************************** +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES +* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE +* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +* +* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS. +******************************************************************************** +* REVISON HISTORY +* DATE | DESCRIPTION +* 03/09/2012| First Release +* 08/11/2012| Code migration +* 09/04/2013| Support Blob Information +*******************************************************************************/ + +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/serio.h> +#include <linux/init.h> +#include <linux/pm.h> +#include <linux/delay.h> +#include <linux/ctype.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/power_supply.h> +#include <linux/firmware.h> +#include <linux/regulator/consumer.h> +#include <linux/of_gpio.h> + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +#include <linux/trustedui.h> +#endif + +#ifdef CONFIG_OF +#ifndef USE_OPEN_CLOSE +#define USE_OPEN_CLOSE +#undef CONFIG_PM +#endif +#endif + +#include <linux/input/mt.h> +#include "ftm4_ts.h" + +static struct i2c_driver fts_i2c_driver; + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +extern int tui_force_close(uint32_t arg); +struct fts_ts_info *tui_tsp_info; +#endif + +#ifdef USE_OPEN_CLOSE +static int fts_input_open(struct input_dev *dev); +static void fts_input_close(struct input_dev *dev); +#ifdef USE_OPEN_DWORK +static void fts_open_work(struct work_struct *work); +#endif +#endif + +static int fts_stop_device(struct fts_ts_info *info); +static int fts_start_device(struct fts_ts_info *info); +static void fts_irq_enable(struct fts_ts_info *info, bool enable); +static void fts_reset_work(struct work_struct *work); +void fts_recovery_cx(struct fts_ts_info *info); +void fts_release_all_finger(struct fts_ts_info *info); +static int fts_suspend(struct i2c_client *client, pm_message_t mesg); +static int fts_resume(struct i2c_client *client); + +#if defined(CONFIG_FB) +static int touch_fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); +#endif + +int fts_write_reg(struct fts_ts_info *info, + unsigned char *reg, unsigned short num_com) +{ + struct i2c_msg xfer_msg[2]; + int ret = 0; + + if (info->touch_stopped) { + tsp_debug_err(&info->client->dev, + "%s: Sensor stopped\n", __func__); + goto exit; + } + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode()) { + tsp_debug_err(&info->client->dev, + "%s TSP no accessible from Linux," + "TUI is enabled!\n", __func__); + return -EIO; + } +#endif + + mutex_lock(&info->i2c_mutex); + + xfer_msg[0].addr = info->client->addr; + xfer_msg[0].len = num_com; + xfer_msg[0].flags = 0; + xfer_msg[0].buf = reg; + + ret = i2c_transfer(info->client->adapter, xfer_msg, 1); + + mutex_unlock(&info->i2c_mutex); + return ret; + + exit: + return -EIO; +} + +int fts_read_reg(struct fts_ts_info *info, unsigned char *reg, int cnum, + unsigned char *buf, int num) +{ + struct i2c_msg xfer_msg[2]; + int ret = 0; + + if (info->touch_stopped) { + tsp_debug_err(&info->client->dev, + "%s: Sensor stopped\n", __func__); + goto exit; + } + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode()) { + tsp_debug_err(&info->client->dev, + "%s TSP no accessible from Linux," + " TUI is enabled!\n", __func__); + return -EIO; + } +#endif + + mutex_lock(&info->i2c_mutex); + + xfer_msg[0].addr = info->client->addr; + xfer_msg[0].len = cnum; + xfer_msg[0].flags = 0; + xfer_msg[0].buf = reg; + + xfer_msg[1].addr = info->client->addr; + xfer_msg[1].len = num; + xfer_msg[1].flags = I2C_M_RD; + xfer_msg[1].buf = buf; + + ret = i2c_transfer(info->client->adapter, xfer_msg, 2); + + mutex_unlock(&info->i2c_mutex); + + return ret; + + exit: + return -EIO; +} + +void fts_delay(unsigned int ms) +{ + if (ms < 20) + usleep_range(ms * 1000, ms * 1000); + else + msleep(ms); +} + +void fts_command(struct fts_ts_info *info, unsigned char cmd) +{ + unsigned char regAdd = 0; + int ret = 0; + + regAdd = cmd; + ret = fts_write_reg(info, ®Add, 1); + tsp_debug_dbg(&info->client->dev, + "FTS Command (%02X) , " + "ret = %d\n", cmd, ret); +} + +void fts_change_scan_rate(struct fts_ts_info *info, unsigned char cmd) +{ + unsigned char regAdd[2] = {0xC3, 0x00}; + int ret = 0; + + regAdd[1] = cmd; + ret = fts_write_reg(info, ®Add[0], 2); + + tsp_debug_dbg(&info->client->dev, + "FTS %s Scan Rate (%02X %02X) , ret = %d\n", + (cmd == FTS_CMD_FAST_SCAN) ? "90Hz" : + (cmd == FTS_CMD_SLOW_SCAN) ? "60Hz" : "30Hz", + regAdd[0], regAdd[1], ret); +} + +int fts_systemreset(struct fts_ts_info *info) +{ + int ret = 0; + unsigned char addr[4] = {0xB6, 0x00, 0x28, 0x80}; + unsigned char addr_wbcrc[4] = {0xB6, 0x00, 0x1E, 0x20}; + + tsp_debug_info(&info->client->dev, "FTS Enable WBCRC\n"); + ret = fts_write_reg(info, &addr_wbcrc[0], 4); + fts_delay(10); + + tsp_debug_dbg(&info->client->dev, "FTS SystemReset\n"); + ret = fts_write_reg(info, &addr[0], 4); + fts_delay(10); + + return ret; +} + +static void fts_interrupt_set(struct fts_ts_info *info, int enable) +{ + unsigned char regAdd[4] = {0xB6, 0x00, 0x2C, INT_ENABLE}; + + if (enable== INT_ENABLE) { + tsp_debug_dbg(&info->client->dev, "FTS INT Enable\n"); + } else { + regAdd[3] = INT_DISABLE; + tsp_debug_dbg(&info->client->dev, "FTS INT Disable\n"); + } + + fts_write_reg(info, ®Add[0], 4); +} + +void fts_get_afe_info(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char regAdd[3]; + unsigned char data[FTS_EVENT_SIZE]; + + /* Reading the final AFE version */ + regAdd[0] = 0xd0; + regAdd[1] = 0x00; + regAdd[2] = 0x52; + + rc = fts_read_reg(info, regAdd, 3, (unsigned char *)data, 3); + if (rc < 0) { + info->afe_ver = 0; + tsp_debug_err(info->dev, + "%s: Read Fail - Final AFE [Data : " + "%2X] AFE Ver [Data : %2X] \n", + __func__, + data[1], + data[2]); + } else + info->afe_ver = data[2]; +} + +static int fts_product_info_read(struct fts_ts_info *info) +{ + unsigned char data[FTS_EVENT_SIZE] = {0,}; + unsigned char prd_info[FTS_LOCKDOWNCODE_SIZE] ={0x0,}; + static u8 addr[2] = {READ_ONE_EVENT, 0}; + int retry = (FTS_RETRY_COUNT * 5); + int total_length = 0; + int offset = 0; + int ret = 0; + int i = 0; + + memset(&info->prd_info, 0, sizeof(struct fts_prd_info)); + + info->fts_interrupt_set(info, INT_DISABLE); + info->fts_command(info, SENSEOFF); + + fts_command(info,LOCKDOWN_READ); + + while (retry--) { + fts_delay(5); + + ret = fts_read_reg(info, &addr[0], 1, &data[0], FTS_EVENT_SIZE); + if (ret < 0) { + tsp_debug_err(info->dev, "ftm4_reg_read fail\n"); + goto error; + } + + if (data[0] == EVENTID_LOCKDOWN_CODE) { + total_length = data[1]; + offset = data[2]; + + tsp_debug_dbg(info->dev, "Total length : %d | offset : %d\n", total_length, offset); + + if (total_length == FTS_LOCKDOWNCODE_SIZE) { + for (i = 0; i < 4; i++) { + if (offset+i >= FTS_LOCKDOWNCODE_SIZE) { + strncpy(&info->prd_info.product_id[0], &prd_info[0], 3); + info->prd_info.chip_rev = (prd_info[3] >> 4) & 0xF; + info->prd_info.fpc_rev = prd_info[3] & 0xF; + info->prd_info.t_sensor_rev = prd_info[4]; + info->prd_info.site = prd_info[5]; + info->prd_info.inspector_no = prd_info[6]; + strncpy(&info->prd_info.date[0], &prd_info[7], 6); + + info->fts_command(info, SENSEON); + info->fts_interrupt_set(info, INT_ENABLE); + return 0; + } + prd_info[offset+i] = data[i+3]; + tsp_debug_dbg(info->dev, "[fts_lockdown_read] code [0x%02X]\n", prd_info[offset+i]); + } + } + } else if ((data[0] == EVENTID_ERROR) && (data[1] == EVENTID_ERROR_LOCKDOWN)) { + switch (data[2] & 0x0F) { + case 0x01: + tsp_debug_err(info->dev, "[fts_lockdown_read] Error - no lockdown code"); + goto error; + case 0x02: + tsp_debug_err(info->dev, "[fts_lockdown_read] Error - Data Corrupted"); + goto error; + case 0x03: + tsp_debug_err(info->dev, "[fts_lockdown_read] Error - Command format invalid"); + goto error; + } + } + } + + tsp_debug_err(info->dev, "[fts_lockdown_read] Error - Time over, retry =%d", retry); +error: + info->fts_command(info, SENSEON); + info->fts_interrupt_set(info, INT_ENABLE); + + return -EINVAL; +} + +int fts_get_version_info(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char addr[3] = {0xD0, 0x00, 0x56}; + unsigned char buff[7] = {0}; + char str[16] = {0}; + int str_ret = 0; + + rc = fts_read_reg(info, &addr[0], 3, &buff[0], 7); + if (rc < 0) { + tsp_debug_err(&info->client->dev, "FTS get version info fail!\n"); + goto error; + } + + info->fw_version_of_ic = buff[1] + (buff[2] << 8); + info->config_version_of_ic = buff[3] + (buff[4] << 8); + info->fw_main_version_of_ic = buff[6] + (buff[5] << 8); + info->ic_fw_ver.build = ((buff[5] >> 4) & 0x0F); + info->ic_fw_ver.major = (buff[5] & 0x0F); + info->ic_fw_ver.minor = buff[6]; + + str_ret += snprintf(str + str_ret, sizeof(str) - str_ret, + "v%d.%02d", + info->ic_fw_ver.major, + info->ic_fw_ver.minor); + + if (info->ic_fw_ver.build) { + str_ret += snprintf(str + str_ret, sizeof(str) - str_ret, + ".%d", + info->ic_fw_ver.build); + } + + fts_get_afe_info(info); + fts_product_info_read(info); + + tsp_debug_info(&info->client->dev, + "IC Firmware Version : 0x%04X [%s] " + "IC Config Version : 0x%04X " + "IC Main Version : 0x%04X " + "AFE Version : 0x%02X\n", + info->fw_version_of_ic, str, + info->config_version_of_ic, + info->fw_main_version_of_ic, + info->afe_ver); + tsp_debug_info(&info->client->dev, + "product id : [%02x %02x %02x]\n", + info->prd_info.product_id[0], + info->prd_info.product_id[1], + info->prd_info.product_id[2]); + tsp_debug_info(&info->client->dev, + "Chip reveion : %d, fpc : %d, t_sensor: %d site : %d , inspector_no : %d\n", + info->prd_info.chip_rev, info->prd_info.fpc_rev, info->prd_info.t_sensor_rev, + info->prd_info.site, info->prd_info.inspector_no); + tsp_debug_info(&info->client->dev, + "date : %02d.%02d.%02d %02d:%02d:%02d\n", + info->prd_info.date[0], info->prd_info.date[1], info->prd_info.date[2], + info->prd_info.date[3], info->prd_info.date[4], info->prd_info.date[5]); + +error: + return rc; +} + +int fts_read_chip_id(struct fts_ts_info *info) +{ + unsigned char regAdd[3] = {0xB6, 0x00, 0x04}; + unsigned char val[7] = {0}; + int ret = 0; + + ret = fts_read_reg(info, regAdd, 3, (unsigned char *)val, 7); + if (ret < 0) { + tsp_debug_err(&info->client->dev, "%s failed. ret: %d\n", + __func__, ret); + return ret; + } + + tsp_debug_dbg(&info->client->dev, + "FTS %02X%02X%02X = %02X %02X %02X %02X %02X %02X\n", + regAdd[0], regAdd[1], regAdd[2], + val[1], val[2], val[3], val[4], + val[5], val[6]); + + if ((val[1] == FTS_ID0) && (val[2] == FTS_ID1)) { + if ((val[5] == 0x00) && (val[6] == 0x00)) { + tsp_debug_err(&info->client->dev, + "\n\r[fts_read_chip_id] Error - No FW : %02X %02X", + val[5], val[6]); + info->flash_corruption_info.fw_broken = true; + } else { + tsp_debug_info(&info->client->dev, + "FTS Chip ID : %02X %02X\n", + val[1], val[2]); + } + } else + return -FTS_ERROR_INVALID_CHIP_ID; + + return ret; +} + +int fts_wait_for_ready(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char addr; + unsigned char data[FTS_EVENT_SIZE]; + int retry = 0; + int err_cnt = 0; + + memset(data, 0x0, FTS_EVENT_SIZE); + + addr = READ_ONE_EVENT; + + while (fts_read_reg(info, &addr, 1, + (unsigned char *)data, FTS_EVENT_SIZE)) { + if (data[0] == EVENTID_CONTROLLER_READY) { + rc = 0; + break; + } + + if (data[0] == EVENTID_ERROR) { + if (data[1] == EVENTID_ERROR_FLASH_CORRUPTION) { + rc = -FTS_ERROR_EVENT_ID; + + tsp_debug_err(&info->client->dev, + "%s: flash corruption:%02X,%02X,%02X\n", + __func__, data[0], + data[1], data[2]); + + switch (data[2]) { + case EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1: + info->flash_corruption_info.cfg_broken = true; + break; + case EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2: + info->flash_corruption_info.cfg_broken = true; + break; + case EVENTID_ERROR_CX_FLASH_CORRUPTION: + info->flash_corruption_info.cx_broken = true; + break; + default: + break; + } + } + + if (err_cnt++ > 32) { + rc = -FTS_ERROR_EVENT_ID; + break; + } + continue; + } + + if (retry++ > FTS_RETRY_COUNT) { + rc = -FTS_ERROR_TIMEOUT; + tsp_debug_err(&info->client->dev, "%s: Time Over\n", + __func__); + + if (info->lowpower_mode) { + schedule_delayed_work(&info->reset_work, + msecs_to_jiffies(10)); + } + break; + } + fts_delay(20); + } + + tsp_debug_dbg(&info->client->dev, + "%s: %02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", + __func__, data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7]); + + return rc; +} + +int fts_get_channel_info(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char cmd[4] = { 0xB2, 0x00, 0x14, 0x02 }; + unsigned char data[FTS_EVENT_SIZE]; + int retry = 0; + + memset(data, 0x0, FTS_EVENT_SIZE); + + fts_write_reg(info, &cmd[0], 4); + cmd[0] = READ_ONE_EVENT; + while (fts_read_reg + (info, &cmd[0], 1, (unsigned char *)data, FTS_EVENT_SIZE)) { + if (data[0] == EVENTID_RESULT_READ_REGISTER) { + if ((data[1] == cmd[1]) && (data[2] == cmd[2])) { + info->SenseChannelLength = data[3]; + info->ForceChannelLength = data[4]; + rc = 0; + break; + } + } + if (retry++ > 30) { + rc = -1; + tsp_debug_err(&info->client->dev, + "Time over - wait for channel info\n"); + break; + } + fts_delay(5); + } + return rc; +} + +#ifdef FTS_SUPPORT_NOISE_PARAM +int fts_get_noise_param_address(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char regAdd[3]; + unsigned char rData[3]; + struct fts_noise_param *noise_param; + int i; + + noise_param = (struct fts_noise_param *)&info->noise_param; + + regAdd[0] = 0xd0; + regAdd[1] = 0x00; + regAdd[2] = 32 * 2; + + if (info->digital_rev == FTS_DIGITAL_REV_1) + rc = fts_read_reg(info, regAdd, 3, + (unsigned char *)noise_param->pAddr, 2); + else { + rc = fts_read_reg(info, regAdd, 3, (unsigned char *)rData, 3); + noise_param->pAddr[0] = rData[1] + (rData[2]<<8); + } + + for (i = 1; i < MAX_NOISE_PARAM; i++) + noise_param->pAddr[i] = noise_param->pAddr[0] + i * 2; + + for (i = 0; i < MAX_NOISE_PARAM; i++) + tsp_debug_dbg(&info->client->dev, + "Get Noise Param%d Address = 0x%4x\n", + i, noise_param->pAddr[i]); + + return rc; +} + +static int fts_get_noise_param(struct fts_ts_info *info) +{ + int rc = 0; + unsigned char regAdd[3]; + unsigned char data[MAX_NOISE_PARAM * 2]; + struct fts_noise_param *noise_param; + int i; + unsigned char buf[3]; + + noise_param = (struct fts_noise_param *)&info->noise_param; + memset(data, 0x0, MAX_NOISE_PARAM * 2); + + for (i = 0; i < MAX_NOISE_PARAM; i++) { + regAdd[0] = 0xb3; + regAdd[1] = 0x00; + regAdd[2] = 0x10; + fts_write_reg(info, regAdd, 3); + + regAdd[0] = 0xb1; + regAdd[1] = (noise_param->pAddr[i] >> 8) & 0xff; + regAdd[2] = noise_param->pAddr[i] & 0xff; + rc = fts_read_reg(info, regAdd, 3, &buf[0], 3); + + noise_param->pData[i] = buf[1]+(buf[2]<<8); + } + + for (i = 0; i < MAX_NOISE_PARAM; i++) { + tsp_debug_dbg(&info->client->dev, + "Get Noise Param%d Address " + "[ 0x%04x ] = 0x%04x\n", i, + noise_param->pAddr[i], + noise_param->pData[i]); + } + + return rc; +} + +static int fts_set_noise_param(struct fts_ts_info *info) +{ + int i; + unsigned char regAdd[5]; + struct fts_noise_param *noise_param; + + noise_param = (struct fts_noise_param *)&info->noise_param; + + for (i = 0; i < MAX_NOISE_PARAM; i++) { + regAdd[0] = 0xb3; + regAdd[1] = 0x00; + regAdd[2] = 0x10; + fts_write_reg(info, regAdd, 3); + + regAdd[0] = 0xb1; + regAdd[1] = (noise_param->pAddr[i] >> 8) & 0xff; + regAdd[2] = noise_param->pAddr[i] & 0xff; + regAdd[3] = noise_param->pData[i] & 0xff; + regAdd[4] = (noise_param->pData[i] >> 8) & 0xff; + fts_write_reg(info, regAdd, 5); + } + + for (i = 0; i < MAX_NOISE_PARAM; i++) { + tsp_debug_dbg(&info->client->dev, + "Set Noise Param%d Address " + "[ 0x%04x ] = 0x%04x\n", + i, + noise_param->pAddr[i], + noise_param->pData[i]); + } + + return 0; +} +#endif + +int fts_cmd_completion_check(struct fts_ts_info *info, uint8_t event1, uint8_t event2, uint8_t event3) +{ + unsigned char val[8]; + unsigned char reg[2] = {0x85, 0}; + int retry = 100; + int rc = 0; + + while (retry--) { + fts_delay(10); + info->fts_read_reg(info, ®[0], 1, &val[0], FTS_EVENT_SIZE); + if ((val[0] == event1) && (val[1] == event2) && (val[2] == event3)) { + tsp_debug_info(&info->client->dev, + "\n\r[fts_cmd_completion_check] OK [%02x][%02x][%02x]", val[0], val[1], val[2]); + return rc; + } else if (val[0] == 0x0F) { + tsp_debug_err(&info->client->dev, + "\n\r[fts_cmd_completion_check] Error - [%02x][%02x][%02x]", val[0], val[1], val[2]); + } + } + + rc = -1; + if (retry <= 0) + tsp_debug_err(&info->client->dev, + "\n\r[fts_cmd_completion_check] Error - Time Over [%02x][%02x][%02x]", event1, event2, event3); + return rc; +} + +static int fts_init(struct fts_ts_info *info) +{ + unsigned char val[16]; + unsigned char regAdd[8]; + int rc = 0; + + fts_systemreset(info); + + rc = fts_wait_for_ready(info); + if (rc == -FTS_ERROR_EVENT_ID) { + info->fw_version_of_ic = 0; + info->config_version_of_ic = 0; + info->fw_main_version_of_ic = 0; + } else { + fts_get_version_info(info); + } + + rc = fts_read_chip_id(info); + if (rc < 0) + tsp_debug_err(&info->client->dev, "%s: Failed to fts_read_chip_id\n", + __func__); + +/* + rc = fts_fw_update(info); + if (rc < 0) + tsp_debug_err(&info->client->dev, "%s: Failed to firmware update\n", + __func__); +*/ + +#ifdef FEATURE_FTS_PRODUCTION_CODE + info->digital_rev = FTS_DIGITAL_REV_2; + rc = info->fts_get_channel_info(info); + if (rc == 0) { + tsp_debug_dbg(&info->client->dev, + "FTS Sense(%02d) Force(%02d)\n", + info->SenseChannelLength, + info->ForceChannelLength); + } else { + tsp_debug_err(&info->client->dev, + "FTS read failed rc = %d\n", rc); + tsp_debug_err(&info->client->dev, + "FTS Initialise Failed\n"); + } + info->pFrame = + kzalloc(info->SenseChannelLength * info->ForceChannelLength * 2, + GFP_KERNEL); + if (info->pFrame == NULL) { + tsp_debug_err(&info->client->dev, + "FTS pFrame kzalloc Failed\n"); + return -ENOMEM; + } + info->cx_data = kzalloc(info->SenseChannelLength * + info->ForceChannelLength, GFP_KERNEL); + if (!info->cx_data) + tsp_debug_err(&info->client->dev, + "%s: cx_data kzalloc Failed\n", __func__); +#endif + fts_command(info, SENSEON); + +#ifdef FTS_SUPPORT_NOISE_PARAM + fts_get_noise_param_address(info); +#endif + /* fts driver set functional feature */ + info->touch_count = 0; + info->palm_pressed = false; + info->flip_enable = false; + info->mainscr_disable = false; + + info->deepsleep_mode = false; + info->wirelesscharger_mode = false; + info->lowpower_mode = false; + info->lowpower_flag = 0x00; + info->fts_power_state = FTS_POWER_STATE_ACTIVE; + + fts_command(info, FORCECALIBRATION); + + fts_interrupt_set(info, INT_ENABLE); + + memset(val, 0x0, 4); + regAdd[0] = READ_STATUS; + fts_read_reg(info, regAdd, 1, (unsigned char *)val, 4); + tsp_debug_dbg(&info->client->dev, + "FTS ReadStatus(0x84) : " + "%02X %02X %02X %02X\n", + val[0], val[1], val[2], val[3]); + + tsp_debug_info(&info->client->dev, + "FTS Initialized\n"); + + return 0; +} + +static void fts_debug_msg_event_handler(struct fts_ts_info *info, + unsigned char data[]) +{ + tsp_debug_dbg(&info->client->dev, + "%s: %02X %02X %02X %02X " + "%02X %02X %02X %02X\n", __func__, + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7]); +} + +static unsigned char fts_event_handler_type_b(struct fts_ts_info *info, + unsigned char data[], + unsigned char LeftEvent) +{ + unsigned char EventNum = 0; + unsigned char NumTouches = 0; + unsigned char TouchID = 0, EventID = 0, status = 0; + unsigned char LastLeftEvent = 0; + int x = 0, y = 0, z = 0; + int bw = 0, bh = 0, palm = 0; + int orient = 0; + +#if defined(CONFIG_INPUT_BOOSTER) + bool booster_restart = false; +#endif + + for (EventNum = 0; EventNum < LeftEvent; EventNum++) { +#ifdef DEBUG + tsp_debug_dbg(&info->client->dev, + "%d %2x %2x %2x %2x %2x %2x %2x %2x\n", + EventNum, + data[EventNum * FTS_EVENT_SIZE], + data[EventNum * FTS_EVENT_SIZE+1], + data[EventNum * FTS_EVENT_SIZE+2], + data[EventNum * FTS_EVENT_SIZE+3], + data[EventNum * FTS_EVENT_SIZE+4], + data[EventNum * FTS_EVENT_SIZE+5], + data[EventNum * FTS_EVENT_SIZE+6], + data[EventNum * FTS_EVENT_SIZE+7]); + tsp_debug_dbg(&info->client->dev, + "fts_power_state (%d)\n", + info->fts_power_state ); +#endif + + if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) + EventID = data[EventNum * FTS_EVENT_SIZE] & 0xFF; + else + EventID = data[EventNum * FTS_EVENT_SIZE] & 0x0F; + + if ((EventID >= 3) && (EventID <= 5)) { + LastLeftEvent = 0; + NumTouches = 1; + TouchID = (data[EventNum * FTS_EVENT_SIZE] >> 4) & 0x0F; + } else { + LastLeftEvent = + data[7 + EventNum * FTS_EVENT_SIZE] & 0x0F; + NumTouches = + (data[1 + EventNum * FTS_EVENT_SIZE] & 0xF0) >> 4; + TouchID = data[1 + EventNum * FTS_EVENT_SIZE] & 0x0F; + EventID = data[EventNum * FTS_EVENT_SIZE] & 0xFF; + status = data[1 + EventNum * FTS_EVENT_SIZE] & 0xFF; + } + + switch (EventID) { + case EVENTID_NO_EVENT: + break; + + case EVENTID_ERROR: + if (data[1 + EventNum * + FTS_EVENT_SIZE] == 0x08) { + /* Get Auto tune fail event */ + if (data[2 + EventNum * + FTS_EVENT_SIZE] == 0x00) { + tsp_debug_err(&info->client->dev, + "[FTS] Fail Mutual Auto tune\n"); + } else if (data[2 + EventNum * + FTS_EVENT_SIZE] == 0x01) { + tsp_debug_err(&info->client->dev, + "[FTS] Fail Self Auto tune\n"); + } + } else if (data[1 + EventNum * + FTS_EVENT_SIZE] == 0x09) + /* Get detect SYNC fail event */ + tsp_debug_err(&info->client->dev, + "[FTS] Fail detect SYNC\n"); + break; + + case EVENTID_HOVER_ENTER_POINTER: + case EVENTID_HOVER_MOTION_POINTER: + x = ((data[4 + EventNum * FTS_EVENT_SIZE] & 0xF0) >> 4) + | ((data[2 + EventNum * FTS_EVENT_SIZE]) << 4); + y = ((data[4 + EventNum * FTS_EVENT_SIZE] & 0x0F) | + ((data[3 + EventNum * FTS_EVENT_SIZE]) << 4)); + + z = data[5 + EventNum * FTS_EVENT_SIZE]; + + input_mt_slot(info->input_dev, 0); + input_mt_report_slot_state(info->input_dev, + MT_TOOL_FINGER, 1); + + input_report_key(info->input_dev, BTN_TOUCH, 0); + input_report_key(info->input_dev, BTN_TOOL_FINGER, 1); + + input_report_abs(info->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(info->input_dev, ABS_MT_DISTANCE, 255 - z); + break; + + case EVENTID_HOVER_LEAVE_POINTER: + input_mt_slot(info->input_dev, 0); + input_mt_report_slot_state(info->input_dev, + MT_TOOL_FINGER, 0); + break; + + case EVENTID_ENTER_POINTER: + if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) + break; + + info->touch_count++; +#if defined(CONFIG_INPUT_BOOSTER) + booster_restart = true; +#endif + case EVENTID_MOTION_POINTER: + if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) { + tsp_debug_info(&info->client->dev, + "%s: low power mode\n", __func__); + fts_release_all_finger(info); + break; + } + + if (info->touch_count == 0) { + tsp_debug_info(&info->client->dev, + "%s: count 0\n", __func__); + fts_release_all_finger(info); + break; + } + + if ((EventID == EVENTID_MOTION_POINTER) && + (info->finger[TouchID].state == + EVENTID_LEAVE_POINTER)) { + tsp_debug_info(&info->client->dev, + "%s: state leave but point is moved.\n", __func__); + break; + } + + if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) + break; + + x = ((data[1 + EventNum * FTS_EVENT_SIZE] + & 0xFF) << 4) + + ((data[3 + EventNum * FTS_EVENT_SIZE] + & 0xF0) >> 4); + y = ((data[2 + EventNum * FTS_EVENT_SIZE] + & 0xFF) << 4) + + (data[3 + EventNum * FTS_EVENT_SIZE] + & 0xF); + + z = data[4 + EventNum * FTS_EVENT_SIZE]; + + bw = data[6 + EventNum * FTS_EVENT_SIZE]; + bh = data[7 + EventNum * FTS_EVENT_SIZE]; + + orient = data[5 + EventNum * FTS_EVENT_SIZE]; + + if (z == 255) { + tsp_debug_info(&info->client->dev, + "%s: Palm Detected\n", __func__); + tsp_debug_info(&info->client->dev, "%s: " + "[ID:%2d X:%4d Y:%4d Z:%4d " + " WM:%4d Wm:%4d Orient:%2d " + "tc:%2d]\n", __func__, + TouchID, x, y, z, + max(bw, bh), min(bw, bh), + orient, info->touch_count); + info->palm_pressed = true; + fts_release_all_finger(info); + return 0; + } + + input_mt_slot(info->input_dev, TouchID); + input_mt_report_slot_state(info->input_dev, + MT_TOOL_FINGER, + 1 + (palm << 1)); + + input_report_key(info->input_dev, BTN_TOUCH, 1); + input_report_key(info->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(info->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(info->input_dev, + ABS_MT_POSITION_Y, y); + + input_report_abs(info->input_dev, + ABS_MT_TOUCH_MAJOR, max(bw, + bh)); + + input_report_abs(info->input_dev, + ABS_MT_TOUCH_MINOR, min(bw, + bh)); + + input_report_abs(info->input_dev, + ABS_MT_PRESSURE, z); + + input_report_abs(info->input_dev, + ABS_MT_ORIENTATION, orient); + + info->finger[TouchID].lx = x; + info->finger[TouchID].ly = y; + + break; + + case EVENTID_LEAVE_POINTER: + if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) + break; + + if (info->palm_pressed) { + tsp_debug_info(&info->client->dev, + "%s: Palm Released\n", __func__); + info->palm_pressed = false; + return 0; + } + + if (info->touch_count <= 0) { + tsp_debug_info(&info->client->dev, + "%s: count 0\n", __func__); + fts_release_all_finger(info); + break; + } + + info->touch_count--; + + input_mt_slot(info->input_dev, TouchID); + + input_mt_report_slot_state(info->input_dev, + MT_TOOL_FINGER, 0); + + if (info->touch_count == 0) { + /* Clear BTN_TOUCH when All touch are released */ + input_report_key(info->input_dev, BTN_TOUCH, 0); + input_report_key(info->input_dev, BTN_TOOL_FINGER, 0); + + } + break; + case EVENTID_STATUS_EVENT: + if (status == STATUS_EVENT_GLOVE_MODE) { + + } else if (status == STATUS_EVENT_RAW_DATA_READY) { + unsigned char regAdd[4] = {0xB0, 0x01, 0x29, 0x01}; + + fts_write_reg(info, ®Add[0], 4); + + tsp_debug_dbg(&info->client->dev, "[FTS] Received the Raw Data Ready Event\n"); + } else if (status == STATUS_EVENT_FORCE_CAL_MUTUAL) { + tsp_debug_dbg(&info->client->dev, "[FTS] Received Force Calibration Mutual only Event\n"); + } else if (status == STATUS_EVENT_FORCE_CAL_SELF) { + tsp_debug_dbg(&info->client->dev, "[FTS] Received Force Calibration Self only Event\n"); + } else if (status == STATUS_EVENT_WATERMODE_ON) { + tsp_debug_dbg(&info->client->dev, "[FTS] Received Water Mode On Event\n"); + } else if (status == STATUS_EVENT_WATERMODE_OFF) { + tsp_debug_dbg(&info->client->dev, "[FTS] Received Water Mode Off Event\n"); + } else if (status == STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK) { + tsp_debug_dbg(&info->client->dev, "[FTS] Received Mutual Calib Frame Check Event\n"); + } else if (status == STATUS_EVENT_SELF_CAL_FRAME_CHECK) { + tsp_debug_dbg(&info->client->dev, "[FTS] Received Self Calib Frame Check Event\n"); + } else { + fts_debug_msg_event_handler(info, + &data[EventNum * + FTS_EVENT_SIZE]); + } + break; + +#ifdef FEATURE_FTS_PRODUCTION_CODE + case EVENTID_RESULT_READ_REGISTER: + procedure_cmd_event(info, &data[EventNum * FTS_EVENT_SIZE]); + break; +#endif /* FEATURE_FTS_PRODUCTION_CODE */ + + default: + fts_debug_msg_event_handler(info, + &data[EventNum * + FTS_EVENT_SIZE]); + continue; + } + + if (EventID == EVENTID_ENTER_POINTER) + tsp_debug_event(&info->client->dev, + "[P] tID:%d x:%d y:%d w:%d " + "h:%d z:%d p:%d tc:%d tm:%d\n", + TouchID, x, y, bw, + bh, z, palm, info->touch_count, info->touch_mode); + else if (EventID == EVENTID_HOVER_ENTER_POINTER) + tsp_debug_event(&info->client->dev, + "[HP] tID:%d x:%d y:%d z:%d\n", + TouchID, x, y, z); + + else if (EventID == EVENTID_LEAVE_POINTER) { + tsp_debug_event(&info->client->dev, + "[R] tID:%d mc: %d tc:%d lx: %d ly: %d " + "Ver[%02X%04X%01X%01X]\n", + TouchID, info->finger[TouchID].mcount, info->touch_count, + info->finger[TouchID].lx, + info->finger[TouchID].ly, + info->panel_revision, + info->fw_main_version_of_ic, + info->flip_enable, + info->mainscr_disable); + + info->finger[TouchID].mcount = 0; + } else if (EventID == EVENTID_HOVER_LEAVE_POINTER) { + tsp_debug_event(&info->client->dev, + "[HR] tID:%d Ver[%02X%04X%01X]\n", + TouchID, + info->panel_revision, + info->fw_main_version_of_ic, + info->flip_enable); + info->finger[TouchID].mcount = 0; + } else if (EventID == EVENTID_MOTION_POINTER) + info->finger[TouchID].mcount++; + + if ((EventID == EVENTID_ENTER_POINTER) || + (EventID == EVENTID_MOTION_POINTER) || + (EventID == EVENTID_LEAVE_POINTER)) + info->finger[TouchID].state = EventID; + } + + input_sync(info->input_dev); + +#if defined(CONFIG_INPUT_BOOSTER) + if ((EventID == EVENTID_ENTER_POINTER) + || (EventID == EVENTID_LEAVE_POINTER)) { + if (booster_restart) + input_booster_send_event(BOOSTER_DEVICE_TOUCH, BOOSTER_MODE_ON); + if (!info->touch_count) + input_booster_send_event(BOOSTER_DEVICE_TOUCH, BOOSTER_MODE_OFF); + } +#endif + + return LastLeftEvent; +} + +#ifdef FTS_SUPPORT_TA_MODE +static void fts_ta_cb(struct fts_callbacks *cb, int ta_status) +{ + struct fts_ts_info *info = + container_of(cb, struct fts_ts_info, callbacks); + + if (ta_status == 0x01 || ta_status == 0x03) { + fts_command(info, FTS_CMD_CHARGER_PLUGGED); + info->TA_Pluged = true; + tsp_debug_dbg(&info->client->dev, + "%s: device_control : CHARGER CONNECTED, ta_status : %x\n", + __func__, ta_status); + } else { + fts_command(info, FTS_CMD_CHARGER_UNPLUGGED); + info->TA_Pluged = false; + tsp_debug_dbg(&info->client->dev, + "%s: device_control : CHARGER DISCONNECTED, ta_status : %x\n", + __func__, ta_status); + } +} +#endif + +/** + * fts_interrupt_handler() + * + * Called by the kernel when an interrupt occurs (when the sensor + * asserts the attention irq). + * + * This function is the ISR thread and handles the acquisition + * and the reporting of finger data when the presence of fingers + * is detected. + */ +static irqreturn_t fts_interrupt_handler(int irq, void *handle) +{ + struct fts_ts_info *info = handle; + unsigned char regAdd[4] = {0xB6, 0x00, 0x23, READ_ALL_EVENT}; + unsigned short evtcount = 0; + + evtcount = 0; + + fts_read_reg(info, ®Add[0], 3, (unsigned char *)&evtcount, 2); + evtcount = evtcount >> 8; + evtcount = evtcount / 2; + + if (evtcount > FTS_FIFO_MAX) + evtcount = FTS_FIFO_MAX; + + if (evtcount > 0) { + memset(info->data, 0x0, FTS_EVENT_SIZE * evtcount); + fts_read_reg(info, ®Add[3], 1, (unsigned char *)info->data, + FTS_EVENT_SIZE * evtcount); + fts_event_handler_type_b(info, info->data, evtcount); + } + return IRQ_HANDLED; +} + +static void fts_irq_enable(struct fts_ts_info *info, + bool enable) +{ + spin_lock(&info->lock); + + if (enable) { + if (atomic_cmpxchg(&info->irq_enabled, 0, 1) == 0) { + tsp_debug_dbg(info->dev, "enable_irq\n"); + enable_irq(info->irq); + } + } else { + if (atomic_cmpxchg(&info->irq_enabled, 1, 0) == 1) { + tsp_debug_dbg(info->dev, "disable_irq\n"); + disable_irq_nosync(info->irq); + } + } + + spin_unlock(&info->lock); +} + +#ifdef CONFIG_OF +#ifdef FTS_SUPPORT_TA_MODE +struct fts_callbacks *fts_charger_callbacks; +void tsp_charger_infom(bool en) +{ + pr_err("[TSP]%s: ta:%d\n", __func__, en); + + if (fts_charger_callbacks && fts_charger_callbacks->inform_charger) + fts_charger_callbacks->inform_charger(fts_charger_callbacks, en); +} +static void fts_tsp_register_callback(void *cb) +{ + fts_charger_callbacks = cb; +} +#endif +static int fts_power_ctrl(void *data, bool on) +{ + struct fts_ts_info *info = (struct fts_ts_info *)data; + const struct fts_i2c_platform_data *pdata = info->board; + struct device *dev = &info->client->dev; + struct regulator *regulator_dvdd = NULL; + struct regulator *regulator_avdd = NULL; + static bool enabled; + int retval = 0; + + if (enabled == on) + return retval; + + /* touch power init */ + if (gpio_is_valid(pdata->vdd_gpio)) { + gpio_request(pdata->vdd_gpio, "touch-vdd"); + } else { + regulator_avdd = regulator_get(NULL, pdata->regulator_avdd); + if (IS_ERR_OR_NULL(regulator_avdd)) { + tsp_debug_err(dev, "%s: " + "Failed to get %s regulator.\n", + __func__, pdata->regulator_avdd); + goto out; + } + } + if (gpio_is_valid(pdata->vio_gpio)) { + gpio_request(pdata->vio_gpio, "touch-vio"); + } else { + regulator_dvdd = regulator_get(NULL, pdata->regulator_dvdd); + if (IS_ERR_OR_NULL(regulator_dvdd)) { + tsp_debug_err(dev, "%s: " + "Failed to get %s regulator.\n", + __func__, pdata->regulator_dvdd); + goto out; + } + } + + tsp_debug_info(dev, "%s: %s\n", __func__, on ? "on" : "off"); + + if (on) { + if (gpio_is_valid(pdata->vdd_gpio)) { + retval = gpio_direction_output(pdata->vdd_gpio, 1); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable vdd: %d\n", + __func__, retval); + } + } else if (!IS_ERR_OR_NULL(regulator_avdd)) { + retval = regulator_enable(regulator_avdd); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable avdd: %d\n", + __func__, retval); + goto out; + } + } + + if (gpio_is_valid(pdata->vio_gpio)) { + retval = gpio_direction_output(pdata->vio_gpio, 1); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable vio: %d\n", + __func__, retval); + } + } else if (!IS_ERR_OR_NULL(regulator_dvdd)) { + retval = regulator_enable(regulator_dvdd); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable dvdd: %d\n", + __func__, retval); + goto out; + } + } + + retval = pinctrl_select_state(pdata->pinctrl, pdata->pins_default); + if (retval < 0) + tsp_debug_err(dev, "%s: " + "Failed to configure tsp_attn pin\n", + __func__); + + fts_delay(5); + } else { + if (gpio_is_valid(pdata->vio_gpio)) { + retval = gpio_direction_output(pdata->vio_gpio, 0); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable vio: %d\n", + __func__, retval); + } + } else if (!IS_ERR_OR_NULL(regulator_dvdd)) { + retval = regulator_disable(regulator_dvdd); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable dvdd: %d\n", + __func__, retval); + goto out; + } + } + + if (gpio_is_valid(pdata->vdd_gpio)) { + retval = gpio_direction_output(pdata->vdd_gpio, 0); + if (retval) + tsp_debug_err(dev, "%s: " + "Failed to enable vdd: %d\n", + __func__, retval); + } else if (!IS_ERR_OR_NULL(regulator_avdd)) { + retval = regulator_disable(regulator_avdd); + if (retval) { + tsp_debug_err(dev, "%s: " + "Failed to enable avdd: %d\n", + __func__, retval); + goto out; + } + } + + retval = pinctrl_select_state(pdata->pinctrl, pdata->pins_sleep); + if (retval < 0) + tsp_debug_err(dev, "%s: Failed to " + "configure tsp_attn pin\n", __func__); + } + + enabled = on; + +out: + regulator_put(regulator_dvdd); + regulator_put(regulator_avdd); + + return retval; +} + +static int fts_parse_dt(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct fts_i2c_platform_data *pdata = dev->platform_data; + struct device_node *np = dev->of_node; + u32 coords[2], lines[2]; + int retval = 0; + + pdata->tspid = of_get_named_gpio(np, "stm,tspid_gpio", 0); + if (gpio_is_valid(pdata->tspid)) + tsp_debug_dbg(dev, + "TSP_ID : %d\n", + gpio_get_value(pdata->tspid)); + else + tsp_debug_err(dev, + "Failed to get tspid gpio\n"); + + pdata->tspid2 = of_get_named_gpio(np, "stm,tspid2_gpio", 0); + if (gpio_is_valid(pdata->tspid2)) + tsp_debug_dbg(dev, + "TSP_ID2 : %d\n", + gpio_get_value(pdata->tspid2)); + else + tsp_debug_err(dev, + "Failed to get tspid2 gpio\n"); + + pdata->gpio = of_get_named_gpio(np, "stm,irq_gpio", 0); + if (gpio_is_valid(pdata->gpio)) { + retval = gpio_request_one(pdata->gpio, + GPIOF_DIR_IN, "stm,tsp_int"); + if (retval) { + tsp_debug_err(dev, + "Unable to request tsp_int [%d]\n", + pdata->gpio); + return -EINVAL; + } + } else { + tsp_debug_err(dev, + "Failed to get irq gpio\n"); + return -EINVAL; + } + client->irq = gpio_to_irq(pdata->gpio); + + if (of_property_read_u32(np, "stm,irq_type", &pdata->irq_type)) { + tsp_debug_err(dev, "Failed to get irq_type property\n"); + return -EINVAL; + } + + if (of_property_read_u32(np, "stm,grip_area", &pdata->grip_area)) + tsp_debug_err(dev, "Failed to get grip_area property\n"); + + if (of_property_read_u32_array(np, "stm,max_coords", coords, 2)) { + tsp_debug_err(dev, "Failed to get max_coords property\n"); + return -EINVAL; + } + pdata->max_x = coords[0]; + pdata->max_y = coords[1]; + + if (of_property_read_u32_array(np, "stm,num_lines", lines, 2)) + tsp_debug_dbg(dev, "skipped to get num_lines property\n"); + else { + pdata->SenseChannelLength = lines[0]; + pdata->ForceChannelLength = lines[1]; + tsp_debug_dbg(dev, "num_of[rx,tx]: [%d,%d]\n", + pdata->SenseChannelLength, pdata->ForceChannelLength); + } + + if (of_property_read_string(np, "stm,regulator_dvdd", &pdata->regulator_dvdd)) { + tsp_debug_err(dev, + "Failed to get regulator_dvdd name property\n"); + } + if (of_property_read_string(np, "stm,regulator_avdd", &pdata->regulator_avdd)) { + tsp_debug_err(dev, + "Failed to get regulator_avdd name property\n"); + } + + pdata->vdd_gpio = of_get_named_gpio(np, "stm,vdd-gpio", 0); + if (gpio_is_valid(pdata->vdd_gpio)) + tsp_debug_dbg(dev, "vdd_gpio : %d\n", + gpio_get_value(pdata->vdd_gpio)); + else + tsp_debug_err(dev, "Failed to get vdd_gpio gpio\n"); + + pdata->vio_gpio = of_get_named_gpio(np, "stm,vio-gpio", 0); + if (gpio_is_valid(pdata->vio_gpio)) + tsp_debug_dbg(dev, "vio_gpio :" + "%d\n", gpio_get_value(pdata->vio_gpio)); + else + tsp_debug_err(dev, "Failed to get vio_gpio gpio\n"); + + pdata->power = fts_power_ctrl; + + /* Optional parmeters(those values are not mandatory) + * do not return error value even if fail to get the value + */ + of_property_read_string(np, "stm,firmware_name", &pdata->firmware_name); + + if (of_property_read_string_index(np, "stm,project_name", 0, &pdata->project_name)) + tsp_debug_dbg(dev, + "skipped to get project_name property\n"); + if (of_property_read_string_index(np, "stm,project_name", 1, &pdata->model_name)) + tsp_debug_dbg(dev, + "skipped to get model_name property\n"); + + pdata->max_width = 28; + pdata->support_hover = true; + pdata->support_mshover = true; +#ifdef FTS_SUPPORT_TA_MODE + pdata->register_cb = fts_tsp_register_callback; +#endif + + return retval; +} +#endif + +static int fts_setup_drv_data(struct i2c_client *client) +{ + int retval = 0; + struct fts_i2c_platform_data *pdata; + struct fts_ts_info *info = NULL; + + /* parse dt */ + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct fts_i2c_platform_data), GFP_KERNEL); + + if (!pdata) { + tsp_debug_err(&client->dev, "Failed to allocate platform data\n"); + return -ENOMEM; + } + + client->dev.platform_data = pdata; + retval = fts_parse_dt(client); + if (retval) { + tsp_debug_err(&client->dev, "Failed to parse dt\n"); + goto error; + } + } else { + pdata = client->dev.platform_data; + } + + if (!pdata) { + tsp_debug_err(&client->dev, "No platform data found\n"); + return -EINVAL; + } + if (!pdata->power) { + tsp_debug_err(&client->dev, "No power contorl found\n"); + retval = -EINVAL; + goto error; + } + + pdata->pinctrl = devm_pinctrl_get(&client->dev); + if (IS_ERR(pdata->pinctrl)) { + tsp_debug_err(&client->dev, "could not get pinctrl\n"); + retval = PTR_ERR(pdata->pinctrl); + goto error; + } + + pdata->pins_default = pinctrl_lookup_state(pdata->pinctrl, "on_state"); + if (IS_ERR(pdata->pins_default)) + tsp_debug_err(&client->dev, "could not get default pinstate\n"); + + pdata->pins_sleep = pinctrl_lookup_state(pdata->pinctrl, "off_state"); + if (IS_ERR(pdata->pins_sleep)) + tsp_debug_err(&client->dev, "could not get sleep pinstate\n"); + + info = kzalloc(sizeof(struct fts_ts_info), GFP_KERNEL); + if (!info) { + tsp_debug_err(&client->dev, + "%s: Failed to alloc mem for info\n", + __func__); + retval = -ENOMEM; + goto error; + } + + info->client = client; + info->board = pdata; + info->irq = client->irq; + info->irq_type = info->board->irq_type; + atomic_set(&info->irq_enabled, 0); + info->touch_stopped = false; + info->panel_revision = info->board->panel_revision; + info->stop_device = fts_stop_device; + info->start_device = fts_start_device; + info->fts_command = fts_command; + info->fts_read_reg = fts_read_reg; + info->fts_write_reg = fts_write_reg; + info->fts_systemreset = fts_systemreset; + info->fts_get_version_info = fts_get_version_info; + info->fts_wait_for_ready = fts_wait_for_ready; +#ifdef FEATURE_FTS_PRODUCTION_CODE + info->fts_get_channel_info = fts_get_channel_info; + info->fts_interrupt_set = fts_interrupt_set; + info->fts_irq_enable = fts_irq_enable; + info->fts_release_all_finger = fts_release_all_finger; +#endif + +#ifdef FTS_SUPPORT_NOISE_PARAM + info->fts_get_noise_param_address = fts_get_noise_param_address; +#endif + +#ifdef USE_OPEN_DWORK + INIT_DELAYED_WORK(&info->open_work, fts_open_work); +#endif + info->delay_time = 300; + INIT_DELAYED_WORK(&info->reset_work, fts_reset_work); + + if (info->board->support_hover) + tsp_debug_info(&info->client->dev, "FTS Support Hover Event\n"); + else + tsp_debug_info(&info->client->dev, "FTS Not support Hover Event\n"); + + i2c_set_clientdata(client, info); + + if (pdata->get_ddi_type) { + info->ddi_type = pdata->get_ddi_type(); + tsp_debug_info(&client->dev, + "%s: DDI Type is %s[%d]\n", + __func__, info->ddi_type ? + "MAGNA" : "SDC", info->ddi_type); + } + + pdata->switch_gpio = of_get_named_gpio(client->dev.of_node, + "stm,switch_gpio", 0); + + if (gpio_is_valid(pdata->switch_gpio)) { + retval = gpio_request_one(pdata->switch_gpio, + GPIOF_OUT_INIT_LOW, + "stm,tsp_i2c_switch"); + if (retval) { + tsp_debug_err(&client->dev, + "Can't req GPIO%d: rev %d\n", + pdata->switch_gpio, retval); + goto error; + } + } else { + tsp_debug_info(&client->dev, "Didn't find switch_gpio = %d\n", + pdata->switch_gpio); + } + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + tui_tsp_info = info; +#endif + return 0; +error: + kfree(info); + if (client->dev.of_node) { + kfree(pdata); + client->dev.platform_data = NULL; + } + return retval; +} + +static int fts_probe(struct i2c_client *client, const struct i2c_device_id *idp) +{ + int retval = 0; + struct fts_ts_info *info = NULL; + static char fts_ts_phys[64] = { 0 }; + int i = 0; + +/* + tsp_debug_info(&client->dev, "FTS Driver [12%s] %s %s\n", + FTS_TS_DRV_VERSION, __DATE__, __TIME__); +*/ + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + tsp_debug_err(&client->dev, "FTS err = EIO!\n"); + return -EIO; + } + + /* Build up driver data */ + retval = fts_setup_drv_data(client); + if (retval < 0) { + tsp_debug_err(&client->dev, + "%s: Failed to set up driver data\n", + __func__); + goto err_setup_drv_data; + } + + info = (struct fts_ts_info *)i2c_get_clientdata(client); + if (!info) { + tsp_debug_err(&client->dev, + "%s: Failed to get driver data\n", __func__); + retval = -ENODEV; + goto err_get_drv_data; + } + + if (info->board->power) + info->board->power(info, true); + + info->dev = &info->client->dev; + info->input_dev = input_allocate_device(); + if (!info->input_dev) { + tsp_debug_err(&info->client->dev, "FTS err = ENOMEM!\n"); + retval = -ENOMEM; + goto err_input_allocate_device; + } + + info->input_dev->dev.parent = &client->dev; + info->input_dev->name = "touchscreen"; + snprintf(fts_ts_phys, sizeof(fts_ts_phys), "%s/input1", + info->input_dev->name); + info->input_dev->phys = fts_ts_phys; + info->input_dev->id.bustype = BUS_I2C; + +#ifdef USE_OPEN_CLOSE + info->input_dev->open = fts_input_open; + info->input_dev->close = fts_input_close; +#endif + + set_bit(EV_SYN, info->input_dev->evbit); + set_bit(EV_KEY, info->input_dev->evbit); + set_bit(EV_ABS, info->input_dev->evbit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, info->input_dev->propbit); +#endif + set_bit(BTN_TOUCH, info->input_dev->keybit); + set_bit(BTN_TOOL_FINGER, info->input_dev->keybit); + + input_mt_init_slots(info->input_dev, FINGER_MAX, INPUT_MT_DIRECT); + input_set_abs_params(info->input_dev, ABS_MT_POSITION_X, + 0, info->board->max_x, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_POSITION_Y, + 0, info->board->max_y, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_PRESSURE, + 0, 255, 0, 0); + + mutex_init(&info->device_mutex); + mutex_init(&info->i2c_mutex); + spin_lock_init(&info->lock); + + info->enabled = false; + mutex_lock(&info->device_mutex); + retval = fts_init(info); + info->reinit_done = true; + mutex_unlock(&info->device_mutex); + if (retval < 0) { + tsp_debug_err(&info->client->dev, "FTS fts_init fail!\n"); + goto err_fts_init; + } + + input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MAJOR, + 0, 255, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MINOR, + 0, 255, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_DISTANCE, + 0, 255, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_ORIENTATION, + 0, 255, 0, 0); + + input_set_drvdata(info->input_dev, info); + i2c_set_clientdata(client, info); + + retval = input_register_device(info->input_dev); + if (retval) { + tsp_debug_err(&info->client->dev, "FTS input_register_device fail!\n"); + goto err_register_input; + } + + for (i = 0; i < FINGER_MAX; i++) { + info->finger[i].state = EVENTID_LEAVE_POINTER; + info->finger[i].mcount = 0; + } + + info->enabled = true; + + retval = request_threaded_irq(info->irq, NULL, + fts_interrupt_handler, info->board->irq_type, + FTS_TS_DRV_NAME, info); + + if (retval < 0) { + tsp_debug_err(&info->client->dev, + "%s: Failed to enable attention interrupt\n", + __func__); + goto err_enable_irq; + } + atomic_set(&info->irq_enabled, 1); + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + trustedui_set_tsp_irq(info->irq); + tsp_debug_info(&client->dev, "%s[%d] called!\n", + __func__, info->irq); +#endif + +#if defined(CONFIG_FB) + info->fb_notif.notifier_call = touch_fb_notifier_callback; + retval = fb_register_client(&info->fb_notif); +#endif + + +#ifdef FTS_SUPPORT_TA_MODE + info->register_cb = info->board->register_cb; + + info->callbacks.inform_charger = fts_ta_cb; + if (info->register_cb) + info->register_cb(&info->callbacks); +#endif + +#ifdef FEATURE_FTS_PRODUCTION_CODE + fts_production_init(info); +#endif /* FEATURE_FTS_PRODUCTION_CODE */ + device_init_wakeup(&client->dev, true); + if (device_may_wakeup(&info->client->dev)) + enable_irq_wake(info->irq); + info->lowpower_mode = true; + + return 0; + +err_enable_irq: + input_unregister_device(info->input_dev); + info->input_dev = NULL; + +err_register_input: + if (info->input_dev) + input_free_device(info->input_dev); + +err_fts_init: + mutex_destroy(&info->device_mutex); + mutex_destroy(&info->i2c_mutex); +err_input_allocate_device: + info->board->power(info, false); + kfree(info); +err_get_drv_data: +err_setup_drv_data: + return retval; +} + +static int fts_remove(struct i2c_client *client) +{ + struct fts_ts_info *info = i2c_get_clientdata(client); + + tsp_debug_info(&info->client->dev, "FTS removed\n"); + +#if defined(CONFIG_FB) + if (fb_unregister_client(&info->fb_notif)) + tsp_debug_err(&info->client->dev, + "%s: Error occured while unregistering fb_notifier.\n", __func__); +#endif + + fts_interrupt_set(info, INT_DISABLE); + fts_command(info, FLUSHBUFFER); + + fts_irq_enable(info, false); + free_irq(info->irq, info); + + input_mt_destroy_slots(info->input_dev); + + input_unregister_device(info->input_dev); + info->input_dev = NULL; + + info->board->power(info, false); + + kfree(info); + + return 0; +} + +#ifdef USE_OPEN_CLOSE +#ifdef USE_OPEN_DWORK +static void fts_open_work(struct work_struct *work) +{ + int retval = 0; + struct fts_ts_info *info = container_of(work, struct fts_ts_info, + open_work.work); + + tsp_debug_info(&info->client->dev, "%s\n", __func__); + + retval = fts_start_device(info); + if (retval < 0) + tsp_debug_err(&info->client->dev, + "%s: Failed to start device\n", __func__); +} +#endif +static int fts_input_open(struct input_dev *dev) +{ + struct fts_ts_info *info = input_get_drvdata(dev); + unsigned char regAdd[4] = {0xB0, 0x01, 0x29, 0x41}; + int retval = 0; + + tsp_debug_info(&info->client->dev, "%s\n", __func__); + +#ifdef USE_OPEN_DWORK + schedule_delayed_work(&info->open_work, + msecs_to_jiffies(TOUCH_OPEN_DWORK_TIME)); +#else + retval = fts_start_device(info); + if (retval < 0) { + tsp_debug_err(&info->client->dev, + "%s: Failed to start device\n", __func__); + goto out; + } +#endif + + tsp_debug_info(&info->client->dev, + "FTS cmd after wakeup : h%d\n", + info->retry_hover_enable_after_wakeup); + + if (info->retry_hover_enable_after_wakeup == 1) { + fts_write_reg(info, ®Add[0], 4); + fts_command(info, FTS_CMD_HOVER_ON); + } + +out: + return 0; +} + +static void fts_input_close(struct input_dev *dev) +{ + struct fts_ts_info *info = input_get_drvdata(dev); + + tsp_debug_info(&info->client->dev, "%s\n", __func__); + +#ifdef USE_OPEN_DWORK + cancel_delayed_work(&info->open_work); +#endif + + fts_stop_device(info); + + info->retry_hover_enable_after_wakeup = 0; +} +#endif + +static void fts_reinit(struct fts_ts_info *info) +{ + fts_systemreset(info); + + fts_wait_for_ready(info); + +#ifdef FTS_SUPPORT_NOISE_PARAM + fts_set_noise_param(info); +#endif + + fts_command(info, SENSEON); + fts_delay(50); + +#ifdef FTS_SUPPORT_TA_MODE + if (info->TA_Pluged) + fts_command(info, FTS_CMD_CHARGER_PLUGGED); +#endif + + info->touch_count = 0; + info->palm_pressed = false; + + fts_command(info, FLUSHBUFFER); + fts_interrupt_set(info, INT_ENABLE); +} + +void fts_release_all_finger(struct fts_ts_info *info) +{ + int i; + + for (i = 0; i < FINGER_MAX; i++) { + input_mt_slot(info->input_dev, i); + input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0); + + if ((info->finger[i].state == EVENTID_ENTER_POINTER) || + (info->finger[i].state == EVENTID_MOTION_POINTER)) { + info->touch_count--; + if (info->touch_count < 0) + info->touch_count = 0; + + tsp_debug_info(&info->client->dev, + "[RA] tID:%d mc: %d tc:%d Ver[%02X%04X%01X%01X]\n", + i, info->finger[i].mcount, info->touch_count, + info->panel_revision, info->fw_main_version_of_ic, + info->flip_enable, info->mainscr_disable); + } + + info->finger[i].state = EVENTID_LEAVE_POINTER; + info->finger[i].mcount = 0; + } + + input_report_key(info->input_dev, BTN_TOUCH, 0); + input_report_key(info->input_dev, BTN_TOOL_FINGER, 0); + +#ifdef CONFIG_INPUT_BOOSTER + input_booster_send_event(BOOSTER_DEVICE_TOUCH, BOOSTER_MODE_FORCE_OFF); +#endif + + input_sync(info->input_dev); +} + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +void trustedui_mode_on(void) +{ + tsp_debug_info(&tui_tsp_info->client->dev, + "%s, release all finger..", __func__); + fts_release_all_finger(tui_tsp_info); +} +#endif + +static void fts_reset_work(struct work_struct *work) +{ + struct fts_ts_info *info = container_of(work, struct fts_ts_info, + reset_work.work); + bool temp_lpm; + + temp_lpm = info->lowpower_mode; + /* Reset-routine must go to power off state */ + info->lowpower_mode = 0; + + tsp_debug_info(&info->client->dev, "%s, Call Power-Off to recover IC, lpm:%d\n", __func__, temp_lpm); + fts_stop_device(info); + + fts_delay(100); /* Delay to discharge the IC from ESD or On-state.*/ + if (fts_start_device(info) < 0) + tsp_debug_err(&info->client->dev, "%s: Failed to start device\n", __func__); + + info->lowpower_mode = temp_lpm; +} + + +static int fts_stop_device(struct fts_ts_info *info) +{ + tsp_debug_dbg(&info->client->dev, "%s\n", __func__); + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) { + tsp_debug_err(&info->client->dev, + "%s TUI cancel event call!\n", __func__); + fts_delay(100); + tui_force_close(1); + fts_delay(200); + if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) { + tsp_debug_err(&info->client->dev, + "%s TUI flag force clear!\n", __func__); + trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED| + TRUSTEDUI_MODE_INPUT_SECURED); + trustedui_set_mode(TRUSTEDUI_MODE_OFF); + } + } +#endif + + mutex_lock(&info->device_mutex); + + if (info->touch_stopped) { + tsp_debug_err(&info->client->dev, + "%s already power off\n", __func__); + goto out; + } + + if (info->lowpower_mode) { + tsp_debug_info(&info->client->dev, + "%s lowpower flag:%d\n", + __func__, info->lowpower_flag); + + info->fts_power_state = FTS_POWER_STATE_LOWPOWER; + + fts_command(info, FLUSHBUFFER); + + fts_command(info, FTS_CMD_LOWPOWER_MODE); + + if (device_may_wakeup(&info->client->dev)) + enable_irq_wake(info->irq); + + fts_command(info, FLUSHBUFFER); + + fts_release_all_finger(info); +#ifdef FTS_SUPPORT_NOISE_PARAM + fts_get_noise_param(info); +#endif + + } else { + fts_interrupt_set(info, INT_DISABLE); + fts_irq_enable(info, false); + + fts_command(info, FLUSHBUFFER); + fts_release_all_finger(info); +#ifdef FTS_SUPPORT_NOISE_PARAM + fts_get_noise_param(info); +#endif + info->touch_stopped = true; + + if (info->board->power) + info->board->power(info, false); + + info->fts_power_state = FTS_POWER_STATE_POWERDOWN; + } + out: + mutex_unlock(&info->device_mutex); + return 0; +} + +static int fts_start_device(struct fts_ts_info *info) +{ + tsp_debug_dbg(&info->client->dev, "%s %s\n", + __func__, + info->lowpower_mode ? + "exit low power mode" : ""); + +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) { + tsp_debug_err(&info->client->dev, + "%s TUI cancel event call!\n", __func__); + fts_delay(100); + tui_force_close(1); + fts_delay(200); + if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) { + tsp_debug_err(&info->client->dev, + "%s TUI flag force clear!\n", __func__); + trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED| + TRUSTEDUI_MODE_INPUT_SECURED); + trustedui_set_mode(TRUSTEDUI_MODE_OFF); + } + } +#endif + + mutex_lock(&info->device_mutex); + + if (!info->touch_stopped && !info->lowpower_mode) { + tsp_debug_err(&info->client->dev, + "%s already power on\n", __func__); + goto out; + } + + fts_release_all_finger(info); + if (info->lowpower_mode) { + /* low power mode command is sent after LCD OFF. */ + /* turn on touch power @ LCD ON */ + if (info->touch_stopped) + goto tsp_power_on; + + disable_irq(info->irq); + + info->reinit_done = false; + fts_reinit(info); + info->reinit_done = true; + + fts_irq_enable(info, true); + + if (device_may_wakeup(&info->client->dev)) + disable_irq_wake(info->irq); + } else { +tsp_power_on: + if (info->board->power) + info->board->power(info, true); + info->touch_stopped = false; + info->reinit_done = false; + + fts_reinit(info); + info->reinit_done = true; + + fts_irq_enable(info, true); + } + + out: + mutex_unlock(&info->device_mutex); + + info->fts_power_state = FTS_POWER_STATE_ACTIVE; + + return 0; +} + +static void fts_shutdown(struct i2c_client *client) +{ + struct fts_ts_info *info = i2c_get_clientdata(client); + + tsp_debug_info(&info->client->dev, "FTS %s called!\n", __func__); + + if (info->lowpower_mode) { + info->lowpower_mode = 0; + tsp_debug_info(&info->client->dev, "FTS lowpower_mode off!\n"); + } + + fts_stop_device(info); +} + +void fts_recovery_cx(struct fts_ts_info *info) +{ + unsigned char regAdd[4] = {0}; + unsigned char buf[8] = {0}; + unsigned char cnt = 100; + int ret = 0; + + regAdd[0] = 0xB6; + regAdd[1] = 0x00; + regAdd[2] = 0x1E; + regAdd[3] = 0x08; + fts_write_reg(info, ®Add[0], 4); /* Loading FW to PRAM without CRC Check */ + fts_delay(30); + + + fts_command(info, CX_TUNNING); + fts_delay(300); + + fts_command(info, FTS_CMD_SAVE_CX_TUNING); + fts_delay(200); + + do { + regAdd[0] = READ_ONE_EVENT; + ret = fts_read_reg(info, regAdd, 1, &buf[0], FTS_EVENT_SIZE); + + fts_delay(10); + + if (cnt-- == 0) + break; + } while (buf[0] != 0x16 || buf[1] != 0x04); + + fts_command(info, SENSEON); + fts_delay(50); + + fts_command(info, FLUSHBUFFER); +} + +#ifdef CONFIG_PM +static int fts_pm_suspend(struct device *dev) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + + tsp_debug_info(&info->client->dev, "%s\n", __func__); + + mutex_lock(&info->input_dev->mutex); + + if (info->input_dev->users) + fts_stop_device(info); + + mutex_unlock(&info->input_dev->mutex); + + return 0; +} + +static int fts_pm_resume(struct device *dev) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + + tsp_debug_info(&info->client->dev, "%s\n", __func__); + + mutex_lock(&info->input_dev->mutex); + + if (info->input_dev->users) + fts_start_device(info); + + mutex_unlock(&info->input_dev->mutex); + + return 0; +} +#endif + +static int fts_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct fts_ts_info *info = i2c_get_clientdata(client); + + tsp_debug_info(&info->client->dev, "%s power state : %d\n", + __func__, info->fts_power_state); + + fts_stop_device(info); + + return 0; +} + +static int fts_resume(struct i2c_client *client) +{ + struct fts_ts_info *info = i2c_get_clientdata(client); + + tsp_debug_info(&info->client->dev, "%s power state : %d\n", + __func__, info->fts_power_state); + /* if resume is called from active state, the i2c bus is not + * switched to AP, skipping resume routine */ + if (info->fts_power_state == FTS_POWER_STATE_ACTIVE) { + tsp_debug_info(&info->client->dev, + "%s: calling resume from active state, " + "skipping\n", __func__); + return 0; + } + + fts_start_device(info); + + return 0; +} + +#if defined(CONFIG_FB) +static int touch_fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fts_ts_info *info = + container_of(self, struct fts_ts_info, fb_notif); + struct fb_event *ev = (struct fb_event *)data; + + if (ev && ev->data && event == FB_EVENT_BLANK) { + int *blank = (int *)ev->data; + + if (*blank == FB_BLANK_UNBLANK) + fts_resume(info->client); + else if (*blank == FB_BLANK_POWERDOWN) + fts_suspend(info->client, PMSG_SUSPEND); + } + + return 0; +} +#endif + +static const struct i2c_device_id fts_device_id[] = { + {FTS_TS_DRV_NAME, 0}, + {} +}; + +#ifdef CONFIG_PM +static const struct dev_pm_ops fts_dev_pm_ops = { + .suspend = fts_pm_suspend, + .resume = fts_pm_resume, +}; +#endif + +#ifdef CONFIG_OF +static struct of_device_id fts_match_table[] = { + { .compatible = "stm,ftm4_fts",}, + { }, +}; +#else +#define fts_match_table NULL +#endif + +static struct i2c_driver fts_i2c_driver = { + .driver = { + .name = FTS_TS_DRV_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = fts_match_table, +#endif +#ifdef CONFIG_PM + .pm = &fts_dev_pm_ops, +#endif + }, + .probe = fts_probe, + .remove = fts_remove, + .shutdown = fts_shutdown, +#if (!defined(CONFIG_FB)) + .suspend = fts_suspend, + .resume = fts_resume, +#endif + .id_table = fts_device_id, +}; + +static int __init fts_driver_init(void) +{ + return i2c_add_driver(&fts_i2c_driver); +} + +static void __exit fts_driver_exit(void) +{ + i2c_del_driver(&fts_i2c_driver); +} + +MODULE_DESCRIPTION("STMicroelectronics MultiTouch IC Driver"); +MODULE_AUTHOR("STMicroelectronics, Inc."); +MODULE_LICENSE("GPL v2"); + +module_init(fts_driver_init); +module_exit(fts_driver_exit); diff --git a/drivers/input/touchscreen/stm/ftm4_ts.h b/drivers/input/touchscreen/stm/ftm4_ts.h new file mode 100644 index 000000000000..90b7d088ba13 --- /dev/null +++ b/drivers/input/touchscreen/stm/ftm4_ts.h @@ -0,0 +1,571 @@ +#ifndef _LINUX_FTM4_TS_H_ +#define _LINUX_FTM4_TS_H_ + +#include <linux/device.h> +#include <linux/hrtimer.h> + +#if defined(CONFIG_FB) +#include <linux/notifier.h> +#include <linux/fb.h> +#endif +#ifdef CONFIG_INPUT_BOOSTER +#include <linux/input/input_booster.h> +#endif +#include <linux/atomic.h> + +#include <linux/printk.h> + +#include "i2c_fts.h" + +#define tsp_debug_dbg(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__) +#define tsp_debug_info(dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__) +#define tsp_debug_err(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__) +#ifdef CONFIG_TOUCHSCREEN_FTM4_SHOW_EVENTS +#define tsp_debug_event(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__) +#else +#define tsp_debug_event(dev, fmt, ...) +#endif + +#define USE_OPEN_CLOSE +#define FEATURE_FTS_PRODUCTION_CODE 1 + +#ifdef USE_OPEN_DWORK +#define TOUCH_OPEN_DWORK_TIME 10 +#endif + +#define FIRMWARE_IC "fts_ic" + +#define FTS_MAX_FW_PATH 64 + +#define FTS_TS_DRV_NAME "fts_touch" +#define FTS_TS_DRV_VERSION "0132" + +#define STM_DEVICE_NAME "STM" + +#define FTS_ID0 0x36 +#define FTS_ID1 0x70 + +#define FTS_SEC_IX1_TX_MULTIPLIER (4) +#define FTS_SEC_IX1_RX_MULTIPLIER (2) + +#define FTS_DIGITAL_REV_1 0x01 +#define FTS_DIGITAL_REV_2 0x02 +#define FTS_FIFO_MAX 32 +#define FTS_EVENT_SIZE 8 +#define FTS_FW_UPDATE_RETRY 3 +#define FTS_LOCKDOWNCODE_SIZE 13 + +#define PRESSURE_MIN 0 +#define PRESSURE_MAX 127 +#define P70_PATCH_ADDR_START 0x00420000 +#define FINGER_MAX 10 +#define AREA_MIN PRESSURE_MIN +#define AREA_MAX PRESSURE_MAX + +#define EVENTID_NO_EVENT 0x00 +#define EVENTID_ENTER_POINTER 0x03 +#define EVENTID_LEAVE_POINTER 0x04 +#define EVENTID_MOTION_POINTER 0x05 +#define EVENTID_HOVER_ENTER_POINTER 0x07 +#define EVENTID_HOVER_LEAVE_POINTER 0x08 +#define EVENTID_HOVER_MOTION_POINTER 0x09 +#define EVENTID_PROXIMITY_IN 0x0B +#define EVENTID_PROXIMITY_OUT 0x0C +#define EVENTID_MSKEY 0x0E +#define EVENTID_ERROR 0x0F +#define EVENTID_CONTROLLER_READY 0x10 +#define EVENTID_SLEEPOUT_CONTROLLER_READY 0x11 +#define EVENTID_RESULT_READ_REGISTER 0x12 +#define EVENTID_STATUS_REQUEST_COMP 0x13 + +#define EVENTID_STATUS_EVENT 0x16 +#define EVENTID_INTERNAL_RELEASE_INFO 0x14 +#define EVENTID_EXTERNAL_RELEASE_INFO 0x15 + +#define EVENTID_FROM_STRING 0x80 +#define EVENTID_GESTURE 0x20 + +#define EVENTID_SIDE_SCROLL 0x40 +/* side touch event-id for debug, remove after f/w fixed */ +#define EVENTID_SIDE_TOUCH_DEBUG 0xDB +#define EVENTID_SIDE_TOUCH 0x0B + +#define EVENTID_ERROR_FLASH_CORRUPTION 0x03 + +/* define flash corruption type */ +#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1 0x01 +#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2 0x02 +#define EVENTID_ERROR_CX_FLASH_CORRUPTION 0x03 + +#define EVENTID_LOCKDOWN_CODE 0x1E +#define EVENTID_ERROR_LOCKDOWN 0x0B + +#define STATUS_EVENT_MUTUAL_AUTOTUNE_DONE 0x01 +#define STATUS_EVENT_SELF_AUTOTUNE_DONE 0x02 +#define STATUS_EVENT_WATER_SELF_AUTOTUNE_DONE 0x4E +#ifdef FTS_SUPPORT_WATER_MODE +#define STATUS_EVENT_WATER_SELF_DONE 0x17 +#endif +#define STATUS_EVENT_FLASH_WRITE_CONFIG 0x03 +#define STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE 0x04 +#define STATUS_EVENT_FORCE_CAL_MUTUAL_SELF 0x05 +#define STATUS_EVENT_FORCE_CAL_DONE 0x06 + +#define STATUS_EVENT_FORCE_CAL_MUTUAL 0x15 +#define STATUS_EVENT_FORCE_CAL_SELF 0x06 +#define STATUS_EVENT_PARAM1_FCAL_MS_SS_DONE 0x23 +#define STATUS_EVENT_WATERMODE_ON 0x07 +#define STATUS_EVENT_WATERMODE_OFF 0x08 +#define STATUS_EVENT_RTUNE_MUTUAL 0x09 +#define STATUS_EVENT_RTUNE_SELF 0x0A +#define STATUS_EVENT_PANEL_TEST_RESULT 0x0B +#define STATUS_EVENT_GLOVE_MODE 0x0C +#define STATUS_EVENT_RAW_DATA_READY 0x0D +#define STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK 0xC1 +#define STATUS_EVENT_SELF_CAL_FRAME_CHECK 0xC2 +#define STATUS_EVENT_CHARGER_CONNECTED 0xCC +#define STATUS_EVENT_CHARGER_DISCONNECTED 0xCD +#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_WRITE_FINISH 0x10 +#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH 0x11 + +#define INT_ENABLE 0x48 +#define INT_DISABLE 0x08 + +#define READ_STATUS 0x84 +#define READ_ONE_EVENT 0x85 +#define READ_ALL_EVENT 0x86 + +#define SENSEOFF 0x92 +#define SENSEON 0x93 +#define FTS_CMD_HOVER_OFF 0x94 +#define FTS_CMD_HOVER_ON 0x95 + +#define FTS_CMD_MSKEY_AUTOTUNE 0x96 +#define FTS_CMD_TRIM_LOW_POWER_OSCILLATOR 0x97 + +#define FTS_CMD_KEY_SENSE_OFF 0x9A +#define FTS_CMD_KEY_SENSE_ON 0x9B +#define FTS_CMD_SET_FAST_GLOVE_MODE 0x9D + +#define FTS_CMD_MSHOVER_OFF 0x9E +#define FTS_CMD_MSHOVER_ON 0x9F +#define FTS_CMD_SET_NOR_GLOVE_MODE 0x9F + +#define FLUSHBUFFER 0xA1 +#define FORCECALIBRATION 0xA2 +#define CX_TUNNING 0xA3 +#define SELF_AUTO_TUNE 0xA4 + +#define FTS_CMD_CHARGER_PLUGGED 0xA8 +#define FTS_CMD_CHARGER_UNPLUGGED 0xAB + +#define FTS_CMD_RELEASEINFO 0xAA +#define FTS_CMD_STYLUS_OFF 0xAB +#define FTS_CMD_STYLUS_ON 0xAC +#define FTS_CMD_LOWPOWER_MODE 0xAD + +#define FTS_CMS_ENABLE_FEATURE 0xC1 +#define FTS_CMS_DISABLE_FEATURE 0xC2 + +#define LOCKDOWN_READ 0xC4 + +#define FTS_CMD_WRITE_PRAM 0xF0 +#define FTS_CMD_BURN_PROG_FLASH 0xF2 +#define FTS_CMD_ERASE_PROG_FLASH 0xF3 +#define FTS_CMD_READ_FLASH_STAT 0xF4 +#define FTS_CMD_UNLOCK_FLASH 0xF7 +#define FTS_CMD_SAVE_FWCONFIG 0xFB +#define FTS_CMD_SAVE_CX_TUNING 0xFC + +#define FTS_CMD_FAST_SCAN 0x01 +#define FTS_CMD_SLOW_SCAN 0x02 +#define FTS_CMD_USLOW_SCAN 0x03 + +#define REPORT_RATE_90HZ 0 +#define REPORT_RATE_60HZ 1 +#define REPORT_RATE_30HZ 2 + +#define FTS_CMD_STRING_ACCESS 0xEC00 +#define FTS_CMD_NOTIFY 0xC0 + +#define FTS_RETRY_COUNT 10 + +/* QUICK SHOT : Quick Camera Launching */ +#define FTS_STRING_EVENT_REAR_CAM (1 << 0) +#define FTS_STRING_EVENT_FRONT_CAM (1 << 1) + +/* SCRUB : Display Watch, Event Status / Fast Access Event */ +#define FTS_STRING_EVENT_WATCH_STATUS (1 << 2) +#define FTS_STRING_EVENT_FAST_ACCESS (1 << 3) +#define FTS_STRING_EVENT_DIRECT_INDICATOR ((1 << 3) | (1 << 2)) +#define FTS_STRING_EVENT_SPAY (1 << 4) +#define FTS_STRING_EVENT_SPAY1 (1 << 5) +#define FTS_STRING_EVENT_SPAY2 ((1 << 4) | (1 << 5)) + +#define FTS_SIDEGESTURE_EVENT_SINGLE_STROKE 0xE0 +#define FTS_SIDEGESTURE_EVENT_DOUBLE_STROKE 0xE1 +#define FTS_SIDEGESTURE_EVENT_INNER_STROKE 0xE3 + +#define FTS_SIDETOUCH_EVENT_LONG_PRESS 0xBB +#define FTS_SIDETOUCH_EVENT_REBOOT_BY_ESD 0xED + +#define FTS_ENABLE 1 +#define FTS_DISABLE 0 + +#define FTS_MODE_QUICK_SHOT (1 << 0) +#define FTS_MODE_SCRUB (1 << 1) +#define FTS_MODE_SPAY (1 << 1) +#define FTS_MODE_QUICK_APP_ACCESS (1 << 2) +#define FTS_MODE_DIRECT_INDICATOR (1 << 3) + +#define TSP_BUF_SIZE 2048 +#define CMD_STR_LEN 32 +#define CMD_RESULT_STR_LEN 2048 +#define CMD_PARAM_NUM 8 + +#define FTS_LOWP_FLAG_QUICK_CAM (1 << 0) +#define FTS_LOWP_FLAG_2ND_SCREEN (1 << 1) +#define FTS_LOWP_FLAG_BLACK_UI (1 << 2) +#define FTS_LOWP_FLAG_QUICK_APP_ACCESS (1 << 3) +#define FTS_LOWP_FLAG_DIRECT_INDICATOR (1 << 4) +#define FTS_LOWP_FLAG_SPAY (1 << 5) +#define FTS_LOWP_FLAG_TEMP_CMD (1 << 6) + +enum fts_error_return { + FTS_NOT_ERROR = 0, + FTS_ERROR_INVALID_CHIP_ID, + FTS_ERROR_INVALID_CHIP_VERSION_ID, + FTS_ERROR_INVALID_SW_VERSION, + FTS_ERROR_EVENT_ID, + FTS_ERROR_TIMEOUT, + FTS_ERROR_FW_UPDATE_FAIL, +}; +#define RAW_MAX 3750 +/** + * struct fts_finger - Represents fingers. + * @ state: finger status (Event ID). + * @ mcount: moving counter for debug. + */ +struct fts_finger { + unsigned char state; + unsigned short mcount; + int lx; + int ly; +}; + +enum tsp_power_mode { + FTS_POWER_STATE_ACTIVE = 0, + FTS_POWER_STATE_LOWPOWER, + FTS_POWER_STATE_POWERDOWN, + FTS_POWER_STATE_DEEPSLEEP, +}; + +enum fts_cover_id { + FTS_FLIP_WALLET = 0, + FTS_VIEW_COVER, + FTS_COVER_NOTHING1, + FTS_VIEW_WIRELESS, + FTS_COVER_NOTHING2, + FTS_CHARGER_COVER, + FTS_VIEW_WALLET, + FTS_LED_COVER, + FTS_CLEAR_FLIP_COVER, + FTS_QWERTY_KEYBOARD_EUR, + FTS_QWERTY_KEYBOARD_KOR, + FTS_MONTBLANC_COVER = 100, +}; + +enum fts_customer_feature { + FTS_FEATURE_ORIENTATION_GESTURE = 1, + FTS_FEATURE_STYLUS, + FTS_FEATURE_QUICK_SHORT_CAMERA_ACCESS, + FTS_FEATURE_SIDE_GUSTURE, + FTS_FEATURE_COVER_GLASS, + FTS_FEATURE_COVER_WALLET, + FTS_FEATURE_COVER_LED, + FTS_FEATURE_COVER_CLEAR_FLIP, + FTS_FEATURE_DUAL_SIDE_GUSTURE, + FTS_FEATURE_CUSTOM_COVER_GLASS_ON, +}; + +enum ftsito_error_type { + NO_ERROR = 0, + ITO_FORCE_OPEN, + ITO_SENSE_OPEN, + ITO_FORCE_SHRT_GND, + ITO_SENSE_SHRT_GND, + ITO_FORCE_SHRT_VCM, + ITO_SENSE_SHRT_VCM, + ITO_FORCE_SHRT_FORCE, + ITO_SENSE_SHRT_SENSE, + ITO_F2E_SENSE, + ITO_FPC_FORCE_OPEN, + ITO_FPC_SENSE_OPEN, + ITO_KEY_FORCE_OPEN, + ITO_KEY_SENSE_OPEN, + ITO_RESERVED0, + ITO_RESERVED1, + ITO_RESERVED2, + ITO_MAX_ERR_REACHED = 0xFF +}; + +struct fts_version { + u8 build: 4; + u8 major: 4; + u8 minor; +}; + +struct fts_prd_info { + u8 product_id[3]; + u8 chip_rev:4; + u8 fpc_rev:4; + u8 t_sensor_rev; + u8 site; + u8 inspector_no; + u8 date[6]; +}; + +struct fts_flash_corruption_info { + bool fw_broken; + bool cfg_broken; + bool cx_broken; +}; + +struct fts_ts_info { + struct device *dev; + struct i2c_client *client; + struct input_dev *input_dev; + struct hrtimer timer; + struct timer_list timer_charger; + struct timer_list timer_firmware; + struct work_struct work; + + int irq; + int irq_type; + atomic_t irq_enabled; + struct fts_i2c_platform_data *board; + void (*register_cb)(void *); + struct fts_callbacks callbacks; + bool enabled; +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#endif +#ifdef FEATURE_FTS_PRODUCTION_CODE + struct device *pdc_dev_ts; + struct list_head cmd_list_head; + u8 cmd_state; + char cmd[CMD_STR_LEN]; + int cmd_param[CMD_PARAM_NUM]; + char cmd_result[CMD_RESULT_STR_LEN]; + int cmd_buf_size; + struct mutex cmd_lock; + bool cmd_is_running; + int SenseChannelLength; + int ForceChannelLength; + short *pFrame; + unsigned char *cx_data; + struct delayed_work cover_cmd_work; + int delayed_cmd_param[2]; +#endif /* FEATURE_FTS_PRODUCTION_CODE */ + bool flip_enable; + bool run_autotune; + bool mainscr_disable; + unsigned int cover_type; + + unsigned char lowpower_flag; + bool lowpower_mode; + bool deepsleep_mode; + bool wirelesscharger_mode; + int fts_power_state; +#ifdef FTS_SUPPORT_TA_MODE + bool TA_Pluged; +#endif + int digital_rev; + int touch_count; + struct fts_finger finger[FINGER_MAX]; + bool palm_pressed; + + int touch_mode; + int retry_hover_enable_after_wakeup; + + struct fts_prd_info prd_info; + int fw_version_of_ic; /* firmware version of IC */ + int fw_version_of_bin; /* firmware version of binary */ + int config_version_of_ic; /* Config release data from IC */ + int config_version_of_bin; /* Config release data from IC */ + unsigned short fw_main_version_of_ic; /* firmware main version of IC */ + unsigned short fw_main_version_of_bin; /* firmware main version of binary */ + int panel_revision; /* Octa panel revision */ + int tspid_val; + int tspid2_val; + +#ifdef USE_OPEN_DWORK + struct delayed_work open_work; +#endif + +#ifdef FTS_SUPPORT_NOISE_PARAM + struct fts_noise_param noise_param; + int (*fts_get_noise_param_address)(struct fts_ts_info *info); +#endif + unsigned int delay_time; + unsigned int debug_string; + struct delayed_work reset_work; + + unsigned int scrub_id; + unsigned int scrub_x; + unsigned int scrub_y; + + struct mutex i2c_mutex; + struct mutex device_mutex; + spinlock_t lock; + bool touch_stopped; + bool reinit_done; + + unsigned char data[FTS_EVENT_SIZE * FTS_FIFO_MAX]; + unsigned char ddi_type; + + char test_fwpath[256]; + struct fts_version ic_fw_ver; + + unsigned char o_afe_ver; + unsigned char afe_ver; + + struct fts_flash_corruption_info flash_corruption_info; + + unsigned int checksum_error; + + int (*stop_device)(struct fts_ts_info *info); + int (*start_device)(struct fts_ts_info *info); + + int (*fts_write_reg)(struct fts_ts_info *info, unsigned char *reg, + unsigned short num_com); + int (*fts_read_reg)(struct fts_ts_info *info, unsigned char *reg, + int cnum, unsigned char *buf, int num); + int (*fts_systemreset)(struct fts_ts_info *info); + int (*fts_wait_for_ready)(struct fts_ts_info *info); + void (*fts_command)(struct fts_ts_info *info, unsigned char cmd); + void (*fts_enable_feature)(struct fts_ts_info *info, unsigned char cmd, + int enable); +#ifdef FEATURE_FTS_PRODUCTION_CODE + int (*fts_get_channel_info)(struct fts_ts_info *info); + int (*fts_get_version_info)(struct fts_ts_info *info); + void (*fts_interrupt_set)(struct fts_ts_info *info, int enable); + void (*fts_irq_enable)(struct fts_ts_info *info, bool enable); + void (*fts_release_all_finger)(struct fts_ts_info *info); +#endif /* FEATURE_FTS_PRODUCTION_CODE */ +}; + +#ifdef FEATURE_FTS_PRODUCTION_CODE +#define FTS_CMD(name, func) .cmd_name = name, .cmd_func = func +struct fts_cmd { + struct list_head list; + const char *cmd_name; + void (*cmd_func)(void *device_data); +}; + +extern struct fts_cmd fts_commands[]; +#endif /* FEATURE_FTS_PRODUCTION_CODE */ + +#define WRITE_CHUNK_SIZE 32 +#define FLASH_CHUNK (64 * 1024) +#define DMA_CHUNK 32 + +#define FW_HEADER_SIZE 64 +#define FW_HEADER_FTB_SIGNATURE 0xAA55AA55 +#define FW_FTB_VER 0x00000001 +#define FW_BYTES_ALLIGN 4 +#define FW_BIN_VER_OFFSET 16 +#define FW_BIN_CONFIG_VER_OFFSET 20 + +/* Command for flash */ +#define FLASH_CMD_UNLOCK 0xF7 +#define FLASH_CMD_WRITE_64K 0xF8 +#define FLASH_CMD_READ_REGISTER 0xF9 +#define FLASH_CMD_WRITE_REGISTER 0xFA + +/* Parameters for commands */ +#define ADDR_WARM_BOOT 0x001E +#define WARM_BOOT_VALUE 0x38 +#define FLASH_ADDR_CODE 0x00000000 +#define FLASH_ADDR_CONFIG 0x0000FC00 + +#define FLASH_UNLOCK_CODE0 0x74 +#define FLASH_UNLOCK_CODE1 0x45 + +#define FLASH_ERASE_UNLOCK_CODE0 0x72 +#define FLASH_ERASE_UNLOCK_CODE1 0x03 +#define FLASH_ERASE_UNLOCK_CODE2 0x02 +#define FLASH_ERASE_CODE0 0x02 +#define FLASH_ERASE_CODE1 0xC0 +#define FLASH_DMA_CODE0 0x05 +#define FLASH_DMA_CODE1 0xC0 +#define FLASH_DMA_CONFIG 0x06 + +enum binfile_type { + BIN_FTS128 = 1, + BIN_FTS256 = 2, + BIN_FTB = 3 +}; + +struct FW_FTB_HEADER { + uint32_t signature; + uint32_t ftb_ver; + uint32_t target; + uint32_t fw_id; + uint32_t fw_ver; + uint32_t cfg_id; + uint32_t cfg_ver; + uint32_t reserved[2]; + uint32_t bl_fw_ver; + uint32_t ext_ver; + uint32_t sec0_size; + uint32_t sec1_size; + uint32_t sec2_size; + uint32_t sec3_size; + uint32_t hdr_crc; +}; + +#ifdef FEATURE_FTS_PRODUCTION_CODE +enum fts_system_information_address { + FTS_SI_FILTERED_RAW_ADDR = 0x02, + FTS_SI_STRENGTH_ADDR = 0x04, + FTS_SI_SELF_FILTERED_FORCE_RAW_ADDR = 0x1E, + FTS_SI_SELF_FILTERED_SENSE_RAW_ADDR = 0x20, + FTS_SI_NOISE_PARAM_ADDR = 0x40, + FTS_SI_PURE_AUTOTUNE_FLAG = 0x4E, + FTS_SI_COMPENSATION_OFFSET_ADDR = 0x50, + FTS_SI_PURE_AUTOTUNE_CONFIG = 0x52, + FTS_SI_FACTORY_RESULT_FLAG = 0x56, + FTS_SI_AUTOTUNE_CNT = 0x58, + FTS_SI_SENSE_CH_LENGTH = 0x5A, /* 2 bytes */ + FTS_SI_FORCE_CH_LENGTH = 0x5C, /* 2 bytes */ + FTS_SI_FINGER_THRESHOLD = 0x60, /* 2 bytes */ + FTS_SI_AUTOTUNE_PROTECTION_CONFIG = 0x62, /* 2 bytes */ + FTS_SI_REPORT_PRESSURE_RAW_DATA = 0x64, /* 2 bytes */ + FTS_SI_SS_KEY_THRESHOLD = 0x66, /* 2 bytes */ + FTS_SI_MS_TUNE_VERSION = 0x68, /* 2 bytes */ + FTS_SI_CONFIG_CHECKSUM = 0x6A, /* 4 bytes */ + FTS_SI_PRESSURE_FILTERED_RAW_ADDR = 0x70, + FTS_SI_PRESSURE_STRENGTH_ADDR = 0x72, + FTS_SI_PRESSURE_THRESHOLD = 0x76, +}; +#endif + +void fts_delay(unsigned int ms); +int fts_cmd_completion_check(struct fts_ts_info *info, uint8_t event1, uint8_t event2, uint8_t event3); +int fts_fw_verify_update(struct fts_ts_info *info); +int fts_get_version_info(struct fts_ts_info *info); +void fts_get_afe_info(struct fts_ts_info *info); +void fts_execute_autotune(struct fts_ts_info *info); +int fts_fw_wait_for_event(struct fts_ts_info *info, unsigned char eid1, unsigned char eid2); +int fts_systemreset(struct fts_ts_info *info); +int fts_wait_for_ready(struct fts_ts_info *info); +int fts_read_chip_id(struct fts_ts_info *info); + +#ifdef FEATURE_FTS_PRODUCTION_CODE +int fts_fw_wait_for_specific_event(struct fts_ts_info *info, + unsigned char eid0, unsigned char eid1, unsigned char eid2); +void procedure_cmd_event(struct fts_ts_info *info, unsigned char *data); +void fts_production_init(void *device_info); +#endif +#endif /* _LINUX_FTM4_TS_H_ */ diff --git a/drivers/input/touchscreen/stm/fts.c b/drivers/input/touchscreen/stm/fts.c new file mode 100644 index 000000000000..0d0ce4165d77 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts.c @@ -0,0 +1,4786 @@ +/** + * fts.c + * + * FTS Capacitive touch screen controller (FingerTipS) + * + * Copyright (C) 2016, STMicroelectronics Limited. + * Authors: AMG(Analog Mems Group) + * + * marco.cali@st.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE + * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT. + * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, + * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM + * THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS. + */ + + +/*! + * \file fts.c + * \brief It is the main file which contains all the most important functions + * generally used by a device driver the driver + */ +#include <linux/device.h> + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <linux/spi/spi.h> +#include <linux/completion.h> +#include <linux/device.h> + +#include <linux/gpio.h> +#include <linux/of_gpio.h> +#include <linux/regulator/consumer.h> + +#include <linux/notifier.h> + +#ifdef KERNEL_ABOVE_2_6_38 +#include <linux/input/mt.h> +#endif + + +#include "fts.h" +#include "fts_lib/ftsCompensation.h" +#include "fts_lib/ftsCore.h" +#include "fts_lib/ftsIO.h" +#include "fts_lib/ftsError.h" +#include "fts_lib/ftsFlash.h" +#include "fts_lib/ftsFrame.h" +#include "fts_lib/ftsGesture.h" +#include "fts_lib/ftsTest.h" +#include "fts_lib/ftsTime.h" +#include "fts_lib/ftsTool.h" + +/* Touch simulation MT slot */ +#define TOUCHSIM_SLOT_ID 0 +#define TOUCHSIM_TIMER_INTERVAL_NS 8333333 + +/* Switch GPIO values */ +#define FTS_SWITCH_GPIO_VALUE_SLPI_MASTER 0 +#define FTS_SWITCH_GPIO_VALUE_AP_MASTER 1 + +/** + * Event handler installer helpers + */ +#define event_id(_e) (EVT_ID_##_e >> 4) +#define handler_name(_h) fts_##_h##_event_handler + +#define install_handler(_i, _evt, _hnd) \ + do { \ + _i->event_dispatch_table[event_id(_evt)] = handler_name(_hnd); \ + } while (0) + + +/* Use decimal-formatted raw data */ +#define RAW_DATA_FORMAT_DEC + +#ifdef KERNEL_ABOVE_2_6_38 +#define TYPE_B_PROTOCOL +#endif + +extern SysInfo systemInfo; +extern TestToDo tests; +#ifdef GESTURE_MODE +extern struct mutex gestureMask_mutex; +#endif + +char fts_ts_phys[64]; /* /< buffer which store the input device name + * assigned by the kernel */ + +static u8 typeOfCommand[CMD_STR_LEN]; /* /< buffer used to store the + * command sent from the MP + * device file node */ +static int numberParameters; /* /< number of parameter passed through the MP + * device file node */ +#ifdef USE_ONE_FILE_NODE +static int feature_feasibility = ERROR_OP_NOT_ALLOW; +#endif +#ifdef GESTURE_MODE +static u8 mask[GESTURE_MASK_SIZE + 2]; +extern u16 gesture_coordinates_x[GESTURE_MAX_COORDS_PAIRS_REPORT]; +extern u16 gesture_coordinates_y[GESTURE_MAX_COORDS_PAIRS_REPORT]; +extern int gesture_coords_reported; +extern struct mutex gestureMask_mutex; +#endif + +#ifdef PHONE_KEY +static u8 key_mask; /* /< store the last update of the key mask + * published by the IC */ +#endif + +extern spinlock_t fts_int; + +static int fts_init_sensing(struct fts_ts_info *info); +static int fts_mode_handler(struct fts_ts_info *info, int force); + +static int fts_chip_initialization(struct fts_ts_info *info, int init_type); + +/** + * Release all the touches in the linux input subsystem + * @param info pointer to fts_ts_info which contains info about device/hw setup + */ +void release_all_touches(struct fts_ts_info *info) +{ + unsigned int type = MT_TOOL_FINGER; + int i; + + for (i = 0; i < TOUCH_ID_MAX; i++) { +#ifdef STYLUS_MODE + if (test_bit(i, &info->stylus_id)) + type = MT_TOOL_PEN; + else + type = MT_TOOL_FINGER; +#endif + input_mt_slot(info->input_dev, i); + input_report_abs(info->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(info->input_dev, type, 0); + input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, -1); + } + input_report_key(info->input_dev, BTN_TOUCH, 0); + input_sync(info->input_dev); + info->touch_id = 0; +#ifdef STYLUS_MODE + info->stylus_id = 0; +#endif +} + + +/** + * @defgroup file_nodes Driver File Nodes + * Driver publish a series of file nodes used to provide several utilities + * to the host and give him access to different API. + * @{ + */ + +/** + * @defgroup device_file_nodes Device File Nodes + * @ingroup file_nodes + * Device File Nodes \n + * There are several file nodes that are associated to the device and which + * are designed to be used by the host to enable/disable features or trigger + * some system specific actions \n + * Usually their final path depend on the definition of device tree node of + * the IC (e.g /sys/devices/soc.0/f9928000.i2c/i2c-6/6-0049) + * @{ + */ +/***************************************** FW UPGGRADE + * ***************************************************/ + +/** + * File node function to Update firmware from shell \n + * echo path_to_fw X Y > fwupdate perform a fw update \n + * where: \n + * path_to_fw = file name or path of the the FW to burn, if "NULL" the default + * approach selected in the driver will be used\n + * X = 0/1 to force the FW update whichever fw_version and config_id; + * 0=perform a fw update only if the fw in the file is newer than the fw in the + * chip \n + * Y = 0/1 keep the initialization data; 0 = will erase the initialization data + * from flash, 1 = will keep the initialization data + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 no + * error) \n + * } = end byte + */ +static ssize_t fts_fwupdate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret, mode[2]; + char path[100 + 1]; /* extra byte to hold '\0'*/ + struct fts_ts_info *info = dev_get_drvdata(dev); + + /* default(if not specified by user) set force = 0 and keep_cx to 1 */ + mode[0] = 0; + mode[1] = 1; + + /* reading out firmware upgrade parameters */ + sscanf(buf, "%100s %d %d", path, &mode[0], &mode[1]); + pr_info("fts_fwupdate_store: path = %s\n", path); + + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true); + + if (info->sensor_sleep) + ret = ERROR_BUS_WR; + else + ret = flashProcedure(path, mode[0], mode[1]); + + info->fwupdate_stat = ret; + + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + + if (ret == ERROR_BUS_WR) + pr_err("%s: bus is not accessible. ERROR %08X\n", + __func__, ret); + else if (ret < OK) + pr_err("%s Unable to upgrade firmware! ERROR %08X\n", + __func__, ret); + + return count; +} + +static ssize_t fts_fwupdate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + + /* fwupdate_stat: ERROR code Returned by flashProcedure. */ + return scnprintf(buf, PAGE_SIZE, "{ %08X }\n", info->fwupdate_stat); +} + + +/***************************************** UTILITIES + * (current fw_ver/conf_id, active mode, file fw_ver/conf_id) + ***************************************************/ +/** + * File node to show on terminal external release version in Little Endian \n + * (first the less significant byte) \n + * cat appid show the external release version of the FW running in the IC + */ +static ssize_t fts_appid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int error; + char temp[100]; + + error = scnprintf(buf, + PAGE_SIZE, + "%s\n", + printHex("ST-V", + systemInfo.u8_releaseInfo, + EXTERNAL_RELEASE_INFO_SIZE, + temp, + sizeof(temp))); + + return error; +} + +/** + * File node to show on terminal the mode that is active on the IC \n + * cat mode_active to show the bitmask which indicate + * the modes/features which are running on the IC in a specific instant of time + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1 = 1 byte in HEX format which represent the actual running scan mode + * (@link scan_opt Scan Mode Options @endlink) \n + * X2 = 1 byte in HEX format which represent the bitmask on which is running + * the actual scan mode \n + * X3X4 = 2 bytes in HEX format which represent a bitmask of the features that + * are enabled at this moment (@link feat_opt Feature Selection Options + * @endlink) \n + * } = end byte + * @see fts_mode_handler() + */ +static ssize_t fts_mode_active_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("Current mode active = %08X\n", info->mode); + return scnprintf(buf, PAGE_SIZE, "{ %08X }\n", info->mode); +} + +/** + * File node to show the fw_ver and config_id of the FW file + * cat fw_file_test show on the kernel log external release + * of the FW stored in the fw file/header file + */ +static ssize_t fts_fw_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + Firmware fw; + int ret; + char temp[100] = { 0 }; + + fw.data = NULL; + ret = readFwFile(info->board->fw_name, &fw, 0); + + if (ret < OK) + pr_err("Error during reading FW file! ERROR %08X\n", ret); + else + pr_info("%s, size = %d bytes\n", + printHex("EXT Release = ", + systemInfo.u8_releaseInfo, + EXTERNAL_RELEASE_INFO_SIZE, + temp, + sizeof(temp)), + fw.data_size); + kfree(fw.data); + return 0; +} + +static ssize_t fts_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + u8 *dump = NULL; + int dumpSize = ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE; + u8 reg; + int written = 0; + int res; + int i; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + pr_err("%s: bus is not accessible.\n", __func__); + written += scnprintf(buf, PAGE_SIZE, + "Bus is not accessible.\n"); + goto exit; + } + + written += scnprintf(buf + written, PAGE_SIZE - written, + "Mode: 0x%08X\n", info->mode); + + res = fts_writeReadU8UX(FTS_CMD_HW_REG_R, ADDR_SIZE_HW_REG, ADDR_ICR, + ®, 1, DUMMY_HW_REG); + if (res < 0) + pr_err("%s: failed to read ICR.\n", __func__); + else + written += scnprintf(buf + written, PAGE_SIZE - written, + "ICR: 0x%02X\n", reg); + + dump = kzalloc(dumpSize, GFP_KERNEL); + if (!dump) { + written += strlcat(buf + written, "Buffer allocation failed!\n", + PAGE_SIZE - written); + goto exit; + } + + res = dumpErrorInfo(dump, ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE); + if (res >= 0) { + written += strlcat(buf + written, "Error dump:", + PAGE_SIZE - written); + for (i = 0; i < dumpSize; i++) { + if (i % 8 == 0) + written += scnprintf(buf + written, + PAGE_SIZE - written, + "\n%02X: ", i); + written += scnprintf(buf + written, + PAGE_SIZE - written, + "%02X ", dump[i]); + } + written += strlcat(buf + written, "\n", PAGE_SIZE - written); + } + +exit: + kfree(dump); + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return written; +} + +#if 0 +/** + * File node to obtain and show strength frame + * cat strength_frame to obtain strength data \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 no + *error) \n + * **** if error code is all 0s **** \n + * FF = 1 byte in HEX format number of rows \n + * SS = 1 byte in HEX format number of columns \n + * N1, ... = the decimal value of each node separated by a coma \n + * ********************************* \n + * } = end byte + */ +static ssize_t fts_strength_frame_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + MutualSenseFrame frame; + int res, count, j, size = (6 * 2) + 1, index = 0; + char *all_strbuff = NULL; + /* char buff[CMD_STR_LEN] = {0}; */ + /* struct i2c_client *client = to_i2c_client(dev); */ + struct fts_ts_info *info = dev_get_drvdata(dev); + + frame.node_data = NULL; + + res = fts_disableInterrupt(); + if (res < OK) + goto END; + + res = senseOn(); + if (res < OK) { + pr_err("%s: could not start scanning! ERROR %08X\n", + __func__, res); + goto END; + } + mdelay(WAIT_FOR_FRESH_FRAMES); + res = senseOff(); + if (res < OK) { + pr_err("%s: could not finish scanning! ERROR %08X\n", + __func__, res); + goto END; + } + + mdelay(WAIT_AFTER_SENSEOFF); + flushFIFO(); + + res = getMSFrame3(MS_STRENGTH, &frame); + if (res < OK) { + pr_err("%s: could not get the frame! ERROR %08X\n", + __func__, res); + goto END; + } else { + size += (res * 6); + pr_info("The frame size is %d words\n", res); + res = OK; + print_frame_short("MS Strength frame =", array1dTo2d_short( + frame.node_data, frame.node_data_size, + frame.header.sense_node), + frame.header.force_node, + frame.header.sense_node); + } + +END: + flushFIFO(); + release_all_touches(info); + fts_mode_handler(info, 1); + + all_strbuff = (char *)kzalloc(size * sizeof(char), GFP_KERNEL); + + if (all_strbuff != NULL) { + snprintf(&all_strbuff[index], 11, "{ %08X", res); + + index += 10; + + if (res >= OK) { + snprintf(&all_strbuff[index], 3, "%02X", + (u8)frame.header.force_node); + index += 2; + snprintf(&all_strbuff[index], 3, "%02X", + (u8)frame.header.sense_node); + + index += 2; + + for (j = 0; j < frame.node_data_size; j++) { + snprintf(&all_strbuff[index], 10, "%d,%n", + frame.node_data[j], &count); + index += count; + } + + kfree(frame.node_data); + } + + snprintf(&all_strbuff[index], 3, " }"); + index += 2; + + count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff); + kfree(all_strbuff); + } else + pr_err("%s: Unable to allocate all_strbuff! ERROR %08X\n", + __func__, ERROR_ALLOC); + + fts_enableInterrupt(); + return count; +} +#endif + +/***************************************** FEATURES + ***************************************************/ + +/* TODO: edit this function according to the features policy to allow during + * the screen on/off, following is shown an example but check always with ST + * for more details */ +/** + * Check if there is any conflict in enable/disable a particular feature + * considering the features already enabled and running + * @param info pointer to fts_ts_info which contains info about the device + * and its hw setup + * @param feature code of the feature that want to be tested + * @return OK if is possible to enable/disable feature, ERROR_OP_NOT_ALLOW + * in case of any other conflict + */ +int check_feature_feasibility(struct fts_ts_info *info, unsigned int feature) +{ + int res = OK; + +/* Example based on the status of the screen and on the feature + * that is trying to enable */ + /*res=ERROR_OP_NOT_ALLOW; + * if(info->resume_bit ==0){ + * switch(feature){ + #ifdef GESTURE_MODE + * case FEAT_SEL_GESTURE: + * res = OK; + * break; + #endif + * default: + * pr_err("%s: Feature not allowed in this + * operating mode! ERROR %08X\n", __func__, res); + * break; + * + * } + * }else{ + * switch(feature){ + #ifdef GESTURE_MODE + * case FEAT_SEL_GESTURE: + #endif + * case FEAT__SEL_GLOVE: // glove mode can only activate + *during sense on + * res = OK; + * break; + * + * default: + * pr_err("%s: Feature not allowed in this + * operating mode! ERROR %08X\n", __func__, res); + * break; + * + * } + * }*/ + + +/* Example based only on the feature that is going to be activated */ + switch (feature) { + case FEAT_SEL_GESTURE: + if (info->cover_enabled == 1) { + res = ERROR_OP_NOT_ALLOW; + pr_err("%s: Feature not allowed when in Cover mode! ERROR %08X\n", + __func__, res); + /* for example here can be placed a code for disabling + * the cover mode when gesture is activated */ + } + break; + + case FEAT_SEL_GLOVE: + if (info->gesture_enabled == 1) { + res = ERROR_OP_NOT_ALLOW; + pr_err("%s: Feature not allowed when Gestures enabled! ERROR %08X\n", + __func__, res); + /* for example here can be placed a code for disabling + * the gesture mode when cover is activated + * (that means that cover mode has + * an higher priority on gesture mode) */ + } + break; + + default: + pr_info("%s: Feature Allowed!\n", __func__); + } + + return res; +} + +#ifdef USE_ONE_FILE_NODE +/** + * File node to enable some feature + * echo XX 00/01 > feature_enable to enable/disable XX + * (possible values @link feat_opt Feature Selection Options @endlink) feature + * cat feature_enable to show the result of enabling/disabling process + * echo 01/00 > feature_enable; cat feature_enable to perform + * both actions stated before in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 = + * no error) \n + * } = end byte + */ +static ssize_t fts_feature_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + char *p = (char *)buf; + unsigned int temp; + int res = OK; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + res = ERROR_BUS_WR; + pr_err("%s: bus is not accessible.", __func__); + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return count; + } + + if ((count - 2 + 1) / 3 != 1) + pr_err("fts_feature_enable: Number of parameter wrong! %d > %d\n", + (count - 2 + 1) / 3, 1); + else { + sscanf(p, "%02X ", &temp); + p += 3; + res = check_feature_feasibility(info, temp); + if (res >= OK) { + switch (temp) { + #ifdef GESTURE_MODE + case FEAT_SEL_GESTURE: + sscanf(p, "%02X ", &info->gesture_enabled); + pr_info("fts_feature_enable: Gesture Enabled = %d\n", + info->gesture_enabled); + break; + #endif + + #ifdef GLOVE_MODE + case FEAT_SEL_GLOVE: + sscanf(p, "%02X ", &info->glove_enabled); + pr_info("fts_feature_enable: Glove Enabled = %d\n", + info->glove_enabled); + break; + #endif + + #ifdef STYLUS_MODE + case FEAT_SEL_STYLUS: + sscanf(p, "%02X ", &info->stylus_enabled); + pr_info("fts_feature_enable: Stylus Enabled = %d\n", + info->stylus_enabled); + break; + #endif + + #ifdef COVER_MODE + case FEAT_SEL_COVER: + sscanf(p, "%02X ", &info->cover_enabled); + pr_info("fts_feature_enable: Cover Enabled = %d\n", + info->cover_enabled); + break; + #endif + + #ifdef CHARGER_MODE + case FEAT_SEL_CHARGER: + sscanf(p, "%02X ", &info->charger_enabled); + pr_info("fts_feature_enable: Charger Enabled = %d\n", + info->charger_enabled); + break; + #endif + + #ifdef GRIP_MODE + case FEAT_SEL_GRIP: + sscanf(p, "%02X ", &info->grip_enabled); + pr_info("fts_feature_enable: Grip Enabled = %d\n", + info->grip_enabled); + break; + #endif + + + + default: + pr_err("fts_feature_enable: Feature %08X not valid! ERROR %08X\n", + temp, ERROR_OP_NOT_ALLOW); + res = ERROR_OP_NOT_ALLOW; + } + feature_feasibility = res; + } + if (feature_feasibility >= OK) + feature_feasibility = fts_mode_handler(info, 1); + else + pr_err("%s: Call echo XX 00/01 > feature_enable with a correct feature value (XX)! ERROR %08X\n", + __func__, res); + } + + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return count; +} + + + +static ssize_t fts_feature_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + + if (feature_feasibility < OK) + pr_err("%s: Call before echo XX 00/01 > feature_enable with a correct feature value (XX)! ERROR %08X\n", + __func__, feature_feasibility); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + feature_feasibility); + + feature_feasibility = ERROR_OP_NOT_ALLOW; + return count; +} + +#else + + +#ifdef GRIP_MODE +/** + * File node to set the grip mode + * echo 01/00 > grip_mode to enable/disable glove mode \n + * cat grip_mode to show the status of the grip_enabled switch \n + * echo 01/00 > grip_mode; cat grip_mode to enable/disable grip + *mode + * and see the switch status in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent the value + * info->grip_enabled (1 = enabled; 0= disabled) \n + * } = end byte + */ +static ssize_t fts_grip_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("%s: grip_enabled = %d\n", __func__, + info->grip_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + info->grip_enabled); + + return count; +} + + +static ssize_t fts_grip_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char *p = (char *)buf; + unsigned int temp = FEAT_DISABLE; + int res; + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + pr_err("%s: bus is not accessible.", __func__); + goto exit; + } + + /* in case of a different elaboration of the input, just modify + * this initial part of the code according to customer needs */ + if ((count + 1) / 3 != 1) + pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n", + __func__, (count + 1) / 3); + else { + res = sscanf(p, "%02X ", &temp); + if ((res != 1) || (temp > FEAT_ENABLE)) { + pr_err("%s: Missing or invalid grip mode(%u)\n", + __func__, temp); + retval = -EINVAL; + goto exit; + } + +/* standard code that should be always used when a feature is enabled! */ +/* first step : check if the wanted feature can be enabled */ +/* second step: call fts_mode_handler to actually enable it */ +/* NOTE: Disabling a feature is always allowed by default */ + res = check_feature_feasibility(info, FEAT_SEL_GRIP); + if (res >= OK || temp == FEAT_DISABLE) { + info->grip_enabled = temp; + res = fts_mode_handler(info, 1); + if (res < OK) + pr_err("%s: Error during fts_mode_handler! ERROR %08X\n", + __func__, res); + } + } + +exit: + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return retval; +} +#endif + +#ifdef CHARGER_MODE +/** + * File node to set the glove mode + * echo XX/00 > charger_mode to value >0 to enable + * (possible values: @link charger_opt Charger Options @endlink), + * 00 to disable charger mode \n + * cat charger_mode to show the status of the charger_enabled switch \n + * echo 01/00 > charger_mode; cat charger_mode to enable/disable + * charger mode and see the switch status in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent the value + * info->charger_enabled (>0 = enabled; 0= disabled) \n + * } = end byte + */ +static ssize_t fts_charger_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("%s: charger_enabled = %d\n", __func__, + info->charger_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + info->charger_enabled); + return count; +} + + +static ssize_t fts_charger_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char *p = (char *)buf; + unsigned int temp = FEAT_DISABLE; + int res; + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + pr_err("%s: bus is not accessible.\n", __func__); + goto exit; + } + +/* in case of a different elaboration of the input, just modify this + * initial part of the code according to customer needs */ + if ((count + 1) / 3 != 1) { + pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n", + __func__, (count + 1) / 3); + retval = -EINVAL; + } else { + res = sscanf(p, "%02X ", &temp); + if ((res != 1) || (temp > FEAT_ENABLE)) { + pr_err("%s: Missing or invalid charger mode (%u)\n", + __func__, temp); + retval = -EINVAL; + goto exit; + } + +/** standard code that should be always used when a feature is enabled! + * first step : check if the wanted feature can be enabled + * second step: call fts_mode_handler to actually enable it + * NOTE: Disabling a feature is always allowed by default + */ + res = check_feature_feasibility(info, FEAT_SEL_CHARGER); + if (res >= OK || temp == FEAT_DISABLE) { + info->charger_enabled = temp; + res = fts_mode_handler(info, 1); + if (res < OK) + pr_err("%s: Error during fts_mode_handler! ERROR %08X\n", + __func__, res); + } + } + +exit: + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return retval; +} +#endif + +#ifdef GLOVE_MODE +/** + * File node to set the glove mode + * echo 01/00 > glove_mode to enable/disable glove mode \n + * cat glove_mode to show the status of the glove_enabled switch \n + * echo 01/00 > glove_mode; cat glove_mode to enable/disable glove mode and + * see the switch status in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent the of value + * info->glove_enabled (1 = enabled; 0= disabled) \n + * } = end byte + */ +static ssize_t fts_glove_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("%s: glove_enabled = %d\n", __func__, info->glove_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + info->glove_enabled); + + return count; +} + + +static ssize_t fts_glove_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + char *p = (char *)buf; + unsigned int temp = FEAT_DISABLE; + int res; + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + pr_err("%s: bus is not accessible.\n", __func__); + goto exit; + } + +/* in case of a different elaboration of the input, just modify this + * initial part of the code according to customer needs */ + if ((count + 1) / 3 != 1) { + pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n", + __func__, (count + 1) / 3); + retval = -EINVAL; + } else { + res = sscanf(p, "%02X ", &temp); + if ((res != 1) || (temp > FEAT_ENABLE)) { + pr_err("%s: Missing or invalid glove mode(%u)\n", + __func__, temp); + retval = -EINVAL; + goto exit; + } + +/* standard code that should be always used when a feature is enabled! */ +/* first step : check if the wanted feature can be enabled */ +/* second step: call fts_mode_handler to actually enable it */ +/* NOTE: Disabling a feature is always allowed by default */ + res = check_feature_feasibility(info, FEAT_SEL_GLOVE); + if (res >= OK || temp == FEAT_DISABLE) { + info->glove_enabled = temp; + res = fts_mode_handler(info, 1); + if (res < OK) + pr_err("%s: Error during fts_mode_handler! ERROR %08X\n", + __func__, res); + } + } + +exit: + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return retval; +} +#endif + + +#ifdef COVER_MODE +/* echo 01/00 > cover_mode to enable/disable cover mode */ +/* cat cover_mode to show the status of the cover_enabled switch + * (example output in the terminal = "AA00000001BB" if the switch is enabled) */ +/* echo 01/00 > cover_mode; cat cover_mode to enable/disable cover mode and + * see the switch status in just one call */ +/* NOTE: the cover can be handled also using a notifier, in this case the body + * of these functions should be copied in the notifier callback */ +/** + * File node to set the cover mode + * echo 01/00 > cover_mode to enable/disable cover mode \n + * cat cover_mode to show the status of the cover_enabled switch \n + * echo 01/00 > cover_mode; cat cover_mode to enable/disable cover mode + * and see the switch status in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which is the value of info->cover_enabled + * (1 = enabled; 0= disabled)\n + * } = end byte \n + * NOTE: \n + * the cover can be handled also using a notifier, in this case the body of + * these functions should be copied in the notifier callback + */ +static ssize_t fts_cover_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("%s: cover_enabled = %d\n", __func__, info->cover_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + info->cover_enabled); + + return count; +} + + +static ssize_t fts_cover_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + char *p = (char *)buf; + unsigned int temp = FEAT_DISABLE; + int res; + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + pr_err("%s: bus is not accessible.\n", __func__); + goto exit; + } + +/* in case of a different elaboration of the input, just modify this + * initial part of the code according to customer needs */ + if ((count + 1) / 3 != 1) + pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n", + __func__, (count + 1) / 3); + else { + res = sscanf(p, "%02X ", &temp); + if ((res != 1) || (temp > FEAT_ENABLE)) { + pr_err("%s: Missing or invalid cover mode(%u)\n", + __func__, temp); + retval = -EINVAL; + goto exit; + } + + p += 3; + +/* standard code that should be always used when a feature is enabled! */ +/* first step : check if the wanted feature can be enabled */ +/* second step: call fts_mode_handler to actually enable it */ +/* NOTE: Disabling a feature is always allowed by default */ + res = check_feature_feasibility(info, FEAT_SEL_COVER); + if (res >= OK || temp == FEAT_DISABLE) { + info->cover_enabled = temp; + res = fts_mode_handler(info, 1); + if (res < OK) + pr_err("%s: Error during fts_mode_handler! ERROR %08X\n", + __func__, res); + } + } + +exit: + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return retval; +} +#endif + +#ifdef STYLUS_MODE +/** + * File node to enable the stylus report + * echo 01/00 > stylus_mode to enable/disable stylus mode \n + * cat stylus_mode to show the status of the stylus_enabled switch \n + * echo 01/00 > stylus_mode; cat stylus_mode to enable/disable stylus mode + * and see the switch status in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which is the value of info->stylus_enabled + * (1 = enabled; 0= disabled)\n + * } = end byte + */ +static ssize_t fts_stylus_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("%s: stylus_enabled = %d\n", __func__, info->stylus_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + info->stylus_enabled); + + return count; +} + + +static ssize_t fts_stylus_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + char *p = (char *)buf; + unsigned int temp = FEAT_DISABLE; + int res; + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + + +/* in case of a different elaboration of the input, just modify this + * initial part of the code according to customer needs */ + if ((count + 1) / 3 != 1) + pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n", + __func__, (count + 1) / 3); + else { + res = sscanf(p, "%02X ", &temp); + if ((res != 1) || (temp > FEAT_ENABLE)) { + pr_err("%s: Missing or invalid stylus mode(%u)\n", + __func__, temp); + retval = -EINVAL; + goto exit; + } + + info->stylus_enabled = temp; + } + +exit: + return retval; +} +#endif + +#endif + +/***************************************** GESTURES + ***************************************************/ +#ifdef GESTURE_MODE +#ifdef USE_GESTURE_MASK /* if this define is used, a gesture bit mask + * is used as method to select the gestures to + * enable/disable */ + +/** + * File node used by the host to set the gesture mask to enable or disable + * echo EE X1 X2 ~~ > gesture_mask set the gesture to disable/enable; + * EE = 00(disable) or 01(enable) \n + * X1 ~~ = gesture mask (example 06 00 ~~ 00 this gesture mask represents + * the gestures with ID = 1 and 2) can be specified + * from 1 to GESTURE_MASK_SIZE bytes, \n + * if less than GESTURE_MASK_SIZE bytes are passed as arguments, + * the omit bytes of the mask maintain the previous settings \n + * if one or more gestures is enabled the driver will automatically + * enable the gesture mode, If all the gestures are disabled the driver + * automatically will disable the gesture mode \n + * cat gesture_mask set inside the specified mask and return an error code + * for the operation \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent an error code for enabling + * the mask (00000000 = no error)\n + * } = end byte \n\n + * if USE_GESTURE_MASK is not define the usage of the function become: \n\n + * echo EE X1 X2 ~~ > gesture_mask set the gesture to disable/enable; + * EE = 00(disable) or 01(enable) \n + * X1 ~~ = gesture IDs (example 01 02 05 represent the gestures with ID = 1, 2 + * and 5) + * there is no limit of the IDs passed as arguments, (@link gesture_opt Gesture + * IDs @endlink) \n + * if one or more gestures is enabled the driver will automatically enable + * the gesture mode. If all the gestures are disabled the driver automatically + * will disable the gesture mode. \n + * cat gesture_mask to show the status of the gesture enabled switch \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which is the value of info->gesture_enabled + * (1 = enabled; 0= disabled)\n + * } = end byte + */ +static ssize_t fts_gesture_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0, res, temp; + struct fts_ts_info *info = dev_get_drvdata(dev); + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + res = ERROR_BUS_WR; + pr_err("%s: bus is not accessible.\n", __func__); + scnprintf(buf, PAGE_SIZE, "{ %08X }\n", res); + goto exit; + } + + if (mask[0] == 0) { + res = ERROR_OP_NOT_ALLOW; + pr_err("%s: Call before echo enable/disable xx xx .... > gesture_mask with a correct number of parameters! ERROR %08X\n", + __func__, res); + } else { + if (mask[1] == FEAT_ENABLE || mask[1] == FEAT_DISABLE) + res = updateGestureMask(&mask[2], mask[0], mask[1]); + else + res = ERROR_OP_NOT_ALLOW; + + if (res < OK) + pr_err("fts_gesture_mask_store: ERROR %08X\n", res); + } + res |= check_feature_feasibility(info, FEAT_SEL_GESTURE); + temp = isAnyGestureActive(); + if (res >= OK || temp == FEAT_DISABLE) + info->gesture_enabled = temp; + + pr_info("fts_gesture_mask_store: Gesture Enabled = %d\n", + info->gesture_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", res); + mask[0] = 0; + +exit: + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return count; +} + + +static ssize_t fts_gesture_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + char *p = (char *)buf; + int n, res; + unsigned int temp = 0; + ssize_t retval = count; + + if ((count + 1) / 3 > GESTURE_MASK_SIZE + 1) { + pr_err("fts_gesture_mask_store: Number of bytes of parameter wrong! %zu > (enable/disable + %d )\n", + (count + 1) / 3, GESTURE_MASK_SIZE); + mask[0] = 0; + } else { + mask[0] = ((count + 1) / 3) - 1; + for (n = 1; n <= (count + 1) / 3; n++) { + res = sscanf(p, "%02X ", &temp); + if (res != 1) { + pr_err("%s: Invalid input\n", __func__); + retval = -EINVAL; + goto exit; + } + + p += 3; + mask[n] = (u8)temp; + pr_info("mask[%d] = %02X\n", n, mask[n]); + } + } +exit: + return retval; +} + +#else /* if this define is not used, to select the gestures to enable/disable + * are used the IDs of the gestures */ +/* echo EE X1 X2 ... > gesture_mask set the gesture to disable/enable; + * EE = 00(disable) or 01(enable); X1 ... = gesture IDs + * (example 01 02 05... represent the gestures with ID = 1, 2 and 5) + * there is no limit of the parameters that can be passed, + * of course the gesture IDs should be valid (all the valid IDs are listed in + * ftsGesture.h) */ +/* cat gesture_mask enable/disable the given gestures, if one or more + * gestures is enabled the driver will automatically enable the gesture mode. + * If all the gestures are disabled the driver automatically will disable the + * gesture mode. + * At the end an error code will be printed + * (example output in the terminal = "AA00000000BB" if there are no errors) */ +/* echo EE X1 X2 ... > gesture_mask; cat gesture_mask perform in one command + * both actions stated before */ +/** + * File node used by the host to set the gesture mask to enable or disable + * echo EE X1 X2 ~~ > gesture_mask set the gesture to disable/enable; + * EE = 00(disable) or 01(enable) \n + * X1 ~ = gesture IDs (example 01 02 05 represent the gestures with ID = 1, 2 + * and 5) + * there is no limit of the IDs passed as arguments, (@link gesture_opt Gesture + * IDs @endlink) \n + * if one or more gestures is enabled the driver will automatically enable + * the gesture mode, If all the gestures are disabled the driver automatically + * will disable the gesture mode \n + * cat gesture_mask to show the status of the gesture enabled switch \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which is the value of info->gesture_enabled + * (1 = enabled; 0= disabled)\n + * } = end byte + */ +static ssize_t fts_gesture_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0; + struct fts_ts_info *info = dev_get_drvdata(dev); + + pr_info("fts_gesture_mask_show: gesture_enabled = %d\n", + info->gesture_enabled); + + count += scnprintf(buf + count, + PAGE_SIZE - count, "{ %08X }\n", + info->gesture_enabled); + + + return count; +} + + +static ssize_t fts_gesture_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + char *p = (char *)buf; + int n; + unsigned int temp = 0; + int res; + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + pr_err("%s: bus is not accessible.\n", __func__); + goto exit; + } + + if ((count + 1) / 3 < 2 || (count + 1) / 3 > GESTURE_MASK_SIZE + 1) { + pr_err("fts_gesture_mask_store: Number of bytes of parameter wrong! %d < or > (enable/disable + at least one gestureID or max %d bytes)\n", + (count + 1) / 3, GESTURE_MASK_SIZE); + mask[0] = 0; + retval = -EINVAL; + } else { + memset(mask, 0, GESTURE_MASK_SIZE + 2); + mask[0] = ((count + 1) / 3) - 1; + res = sscanf(p, "%02X ", &temp); + if (res != 1) { + pr_err("%s: Invalid input(%u)\n",__func__, temp); + mask[0] = 0; + retval = -EINVAL; + goto bad_param; + } + + p += 3; + mask[1] = (u8)temp; + for (n = 1; n < (count + 1) / 3; n++) { + res = sscanf(p, "%02X ", &temp); + if (res != 1) { + pr_err("%s: Invalid input\n", __func__); + mask[0] = 0; + retval = -EINVAL; + goto bad_param; + } + + p += 3; + fromIDtoMask((u8)temp, &mask[2], GESTURE_MASK_SIZE); + } + + for (n = 0; n < GESTURE_MASK_SIZE + 2; n++) + pr_info("mask[%d] = %02X\n", n, mask[n]); + } + +bad_param; + if (mask[0] == 0) { + res = ERROR_OP_NOT_ALLOW; + pr_err("%s: Call before echo enable/disable xx xx .... > gesture_mask with a correct number of parameters! ERROR %08X\n", + __func__, res); + + goto exit; + } + + if (mask[1] == FEAT_ENABLE || mask[1] == FEAT_DISABLE) + res = updateGestureMask(&mask[2], mask[0], mask[1]); + else + res = ERROR_OP_NOT_ALLOW; + + if (res < OK) + pr_err("fts_gesture_mask_store: ERROR %08X\n", res); + + res = check_feature_feasibility(info, FEAT_SEL_GESTURE); + temp = isAnyGestureActive(); + if (res >= OK || temp == FEAT_DISABLE) + info->gesture_enabled = temp; + res = fts_mode_handler(info, 0); + +exit: + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + return retval; +} + + +#endif + + +/** + * File node to read the coordinates of the last gesture drawn by the user \n + * cat gesture_coordinates to obtain the gesture coordinates \n + * the string returned in the shell follow this up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 = + *OK) \n + * \n if error code = 00000000 \n + * CC = 1 byte in HEX format number of coords (pair of x,y) returned \n + * XXiYYi ... = XXi 2 bytes in HEX format for x[i] and + * YYi 2 bytes in HEX format for y[i] (big endian) \n + * \n + * } = end byte + */ +static ssize_t fts_gesture_coordinates_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int size = PAGE_SIZE; + int count = 0, res, i = 0; + + pr_info("%s: Getting gestures coordinates...\n", __func__); + + if (gesture_coords_reported < OK) { + pr_err("%s: invalid coordinates! ERROR %08X\n", + __func__, gesture_coords_reported); + res = gesture_coords_reported; + } else { + size += gesture_coords_reported * 2 * 4 + 2; + /* coords are pairs of x,y (*2) where each coord is + * short(2bytes=4char)(*4) + 1 byte(2char) num of coords (+2) + **/ + res = OK; /* set error code to OK */ + } + + + count += scnprintf(buf + count, + size - count, "{ %08X", res); + + if (res >= OK) { + count += scnprintf(buf + count, + size - count, "%02X", + gesture_coords_reported); + + for (i = 0; i < gesture_coords_reported; i++) { + count += scnprintf(buf + count, + size - count, + "%04X", + gesture_coordinates_x[i]); + count += scnprintf(buf + count, + size - count, + "%04X", + gesture_coordinates_y[i]); + } + } + + count += scnprintf(buf + count, size - count, " }\n"); + pr_info("%s: Getting gestures coordinates FINISHED!\n", __func__); + + return count; +} +#endif + +/* Touch simulation hr timer expiry callback */ +static enum hrtimer_restart touchsim_timer_cb(struct hrtimer *timer) +{ + struct fts_touchsim *touchsim = container_of(timer, + struct fts_touchsim, + hr_timer); + enum hrtimer_restart retval = HRTIMER_NORESTART; + + if (touchsim->is_running) { + hrtimer_forward_now(timer, + ns_to_ktime(TOUCHSIM_TIMER_INTERVAL_NS)); + retval = HRTIMER_RESTART; + } + + /* schedule the task to report touch coordinates to kernel + * input subsystem + */ + queue_work(touchsim->wq, &touchsim->work); + + return retval; +} + +/* Compute the next touch coordinate(x,y) */ +static void touchsim_refresh_coordinates(struct fts_touchsim *touchsim) +{ + struct fts_ts_info *info = container_of(touchsim, + struct fts_ts_info, + touchsim); + + const int x_start = info->board->x_axis_max / 10; + const int x_max = (info->board->x_axis_max * 9) / 10; + const int y_start = info->board->y_axis_max / 4; + const int y_max = info->board->y_axis_max / 2; + + touchsim->x += touchsim->x_step; + touchsim->y += touchsim->y_step; + + if (touchsim->x < x_start || touchsim->x > x_max) + touchsim->x_step *= -1; + + if (touchsim->y < y_start || touchsim->y > y_max) + touchsim->y_step *= -1; +} + +/* Report touch contact */ +static void touchsim_report_contact_event(struct input_dev *dev, int slot_id, + int x, int y, int z) +{ + /* report the cordinates to the input subsystem */ + input_mt_slot(dev, slot_id); + input_report_key(dev, BTN_TOUCH, true); + input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); + input_report_abs(dev, ABS_MT_POSITION_X, x); + input_report_abs(dev, ABS_MT_POSITION_Y, y); + input_report_abs(dev, ABS_MT_PRESSURE, z); +} + +/* Work callback to report the touch co-ordinates to input subsystem */ +static void touchsim_work(struct work_struct *work) +{ + struct fts_touchsim *touchsim = container_of(work, + struct fts_touchsim, + work); + struct fts_ts_info *info = container_of(touchsim, + struct fts_ts_info, + touchsim); + /* prevent CPU from entering deep sleep */ + cpu_latency_qos_update_request(&info->pm_qos_req, 100); + + /* Notify the PM core that the wakeup event will take 1 sec */ + __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ)); + + /* get the next touch coordinates */ + touchsim_refresh_coordinates(touchsim); + + /* send the touch co-ordinates */ + touchsim_report_contact_event(info->input_dev, TOUCHSIM_SLOT_ID, + touchsim->x, touchsim->y, 1); + + input_sync(info->input_dev); + + cpu_latency_qos_update_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE); +} + +/* Start the touch simulation */ +static int touchsim_start(struct fts_touchsim *touchsim) +{ + struct fts_ts_info *info = container_of(touchsim, + struct fts_ts_info, + touchsim); + if (!touchsim->wq) { + pr_err("%s: touch simulation test wq is not available!\n", + __func__); + return -EFAULT; + } + + if (touchsim->is_running) { + pr_err("%s: test in progress!\n", __func__); + return -EBUSY; + } + + /* setup the initial touch coordinates*/ + touchsim->x = info->board->x_axis_max / 10; + touchsim->y = info->board->y_axis_max / 4; + + touchsim->is_running = true; + + touchsim->x_step = 2; + touchsim->y_step = 2; + + /* Disable touch interrupts from hw */ + fts_disableInterrupt(); + + /* Release all touches in the linux input subsystem */ + release_all_touches(info); + + /* setup and start a hr timer to be fired every 120Hz(~8.333333ms) */ + hrtimer_init(&touchsim->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + touchsim->hr_timer.function = touchsim_timer_cb; + hrtimer_start(&touchsim->hr_timer, + ns_to_ktime(TOUCHSIM_TIMER_INTERVAL_NS), + HRTIMER_MODE_ABS); + + return OK; +} + +/* Stop the touch simulation test */ +static int touchsim_stop(struct fts_touchsim *touchsim) +{ + struct fts_ts_info *info = container_of(touchsim, + struct fts_ts_info, + touchsim); + if (!touchsim->is_running) { + pr_err("%s: test is not in progress!\n", __func__); + return -EINVAL; + } + + /* Set the flag here to make sure flushed work doesn't + * re-start the timer + */ + touchsim->is_running = false; + + hrtimer_cancel(&touchsim->hr_timer); + + /* flush any pending work */ + flush_workqueue(touchsim->wq); + + /* Release all touches in the linux input subsystem */ + release_all_touches(info); + + /* re enable the hw touch interrupt */ + fts_enableInterrupt(); + + return OK; +} + +/** sysfs file node to handle the touch simulation test request. + * "cat touchsim" shows if the test is running + * Possible outputs: + * 1 = test running. + * 0 = test not running. + */ +static ssize_t fts_touch_simulation_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", + info->touchsim.is_running ? 1 : 0); +} + +/** sysfs file node to handle the touch simulation test request. + * "echo <cmd> > touchsim" to execute a command + * Possible commands (cmd): + * 1 = start the test if not already running. + * 0 = stop the test if its running. + */ +static ssize_t fts_touch_simulation_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct fts_ts_info *info = dev_get_drvdata(dev); + ssize_t retval = count; + u8 result; + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + retval = -EBUSY; + goto out; + } + + if (kstrtou8(buf, 16, &result)) { + pr_err("%s:bad input. valid inputs are either 0 or 1!\n", + __func__); + retval = -EINVAL; + goto unlock; + } + + if (result == 1) + touchsim_start(&info->touchsim); + else if (result == 0) + touchsim_stop(&info->touchsim); + else + pr_err("%s:Invalid cmd(%u). valid cmds are either 0 or 1!\n", + __func__, result); +unlock: + mutex_unlock(&info->diag_cmd_lock); +out: + return retval; +} + +/***************************************** PRODUCTION TEST + ***************************************************/ + +/** + * File node to execute the Mass Production Test or to get data from the IC + * (raw or ms/ss init data) + * echo cmd > stm_fts_cmd to execute a command \n + * cat stm_fts_cmd to show the result of the command \n + * echo cmd > stm_fts_cmd; cat stm_fts_cmd to execute and show the result + * in just one call \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * X1X2X3X4 = 4 bytes in HEX format which represent an error_code (00000000 = + * OK)\n + * (optional) data = data coming from the command executed represented as HEX + * string \n + * Not all the command return additional data \n + * } = end byte \n + * \n + * Possible commands (cmd): \n + * - 00 = MP Test -> return error_code \n + * - 01 = ITO Test -> return error_code \n + * - 03 = MS Raw Test -> return error_code \n + * - 04 = MS Init Data Test -> return error_code \n + * - 05 = SS Raw Test -> return error_code \n + * - 06 = SS Init Data Test -> return error_code \n + * - 13 = Read 1 MS Raw Frame -> return additional data: MS frame row after row + * \n + * - 14 = Read MS Init Data -> return additional data: MS init data row after + * row \n + * - 15 = Read 1 SS Raw Frame -> return additional data: SS frame, + * force channels followed by sense channels \n + * - 16 = Read SS Init Data -> return additional data: SS Init data, + * first IX for force and sense channels and then CX for force and sense + * channels \n + * - F0 = Perform a system reset -> return error_code \n + * - F1 = Perform a system reset and reenable the sensing and the interrupt + */ +static ssize_t stm_fts_cmd_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + u8 result, n = 0; + struct fts_ts_info *info = dev_get_drvdata(dev); + char *p, *temp_buf, *token; + ssize_t buf_len; + ssize_t retval = count; + + if (!count) { + pr_err("%s: Invalid input buffer length!\n", __func__); + retval = -EINVAL; + goto out; + } + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + retval = -EINVAL; + goto out; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + retval = -EBUSY; + goto out; + } + + memset(typeOfCommand, 0, sizeof(typeOfCommand)); + + buf_len = strlen(buf) + 1; + temp_buf = kmalloc(buf_len, GFP_KERNEL); + if (!temp_buf) { + pr_err("%s: memory allocation failed for length(%zu)!", + __func__, buf_len); + retval = -ENOMEM; + goto unlock; + } + + strlcpy(temp_buf, buf, buf_len); + p = temp_buf; + + /* Parse the input string to retrieve 2 hex-digit width cmds/args + * separated by one or more spaces. + * Any input not equal to 2 hex-digit width are ignored. + * A single 2 hex-digit width command w/ or w/o space is allowed. + * Inputs not in the valid hex range are also ignored. + * In case of encountering any of the above failure, the entire input + * buffer is discarded. + */ + while (p && (n < CMD_STR_LEN)) { + + while (isspace(*p)) { + p++; + } + + token = strsep(&p, " "); + + if (!token || *token == '\0') { + break; + } + + if (strlen(token) != 2 ) { + pr_debug("%s: bad len. len=%zu\n", + __func__, strlen(token)); + n = 0; + break; + } + + if (kstrtou8(token, 16, &result)) { + /* Conversion failed due to bad input. + * Discard the entire buffer. + */ + pr_debug("%s: bad input\n", __func__); + n = 0; + break; + } + + /* found a valid cmd/args */ + typeOfCommand[n] = result; + pr_debug("%s: typeOfCommand[%d]=%02X\n", + __func__, n, typeOfCommand[n]); + + n++; + } + + if (n == 0) { + pr_err("%s: Found invalid cmd/arg\n", __func__); + retval = -EINVAL; + } + + numberParameters = n; + pr_info("%s: Number of Parameters = %d\n", __func__, numberParameters); + + kfree(temp_buf); + +unlock: + mutex_unlock(&info->diag_cmd_lock); +out: + return retval; +} + +static ssize_t stm_fts_cmd_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int res, j, doClean = 0, index = 0; + int size = (6 * 2) + 1; + int nodes = 0; + int init_type = SPECIAL_PANEL_INIT; + u8 *all_strbuff = buf; + struct fts_ts_info *info = dev_get_drvdata(dev); + + MutualSenseData compData; + SelfSenseData comData; + MutualSenseFrame frameMS; + SelfSenseFrame frameSS; + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + return -EINVAL; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + return -EBUSY; + } + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + res = ERROR_BUS_WR; + pr_err("%s: bus is not accessible.\n", __func__); + scnprintf(buf, PAGE_SIZE, "{ %08X }\n", res); + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + mutex_unlock(&info->diag_cmd_lock); + return 0; + } + + if (numberParameters >= 1) { + res = fts_disableInterrupt(); + if (res < 0) { + pr_err("fts_disableInterrupt: ERROR %08X\n", res); + res = (res | ERROR_DISABLE_INTER); + goto END; + } + + switch (typeOfCommand[0]) { + /*ITO TEST*/ + case 0x01: + res = production_test_ito(LIMITS_FILE, &tests); + break; + + /*PRODUCTION TEST*/ + case 0x02: + if (systemInfo.u8_cfgAfeVer != systemInfo.u8_cxAfeVer) { + res = ERROR_OP_NOT_ALLOW; + pr_err("Miss match in CX version! MP test not allowed with wrong CX memory! ERROR %08X\n", + res); + break; + } + res = production_test_initialization(init_type); + break; + + case 0x00: + if (systemInfo.u8_cfgAfeVer != systemInfo.u8_cxAfeVer) { + res = ERROR_OP_NOT_ALLOW; + pr_err("Miss match in CX version! MP test not allowed with wrong CX memory! ERROR %08X\n", + res); + break; + } + + res = production_test_main(LIMITS_FILE, 1, init_type, + &tests); + break; + + /*read mutual raw*/ + case 0x13: + if (numberParameters > 1) { + pr_info("Get 1 MS Frame\n"); + setScanMode(SCAN_MODE_LOCKED, typeOfCommand[1]); + mdelay(WAIT_FOR_FRESH_FRAMES); + setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + /* Delete the events related to some touch + * (allow to call this function while touching + * the screen without having a flooding of the + * FIFO) + */ + flushFIFO(); + res = getMSFrame3(MS_RAW, &frameMS); + if (res < 0) { + pr_err("Error while taking the MS frame... ERROR %08X\n", + res); + } else { + pr_info("The frame size is %d words\n", + res); +#ifdef RAW_DATA_FORMAT_DEC + size += 3 * 2 + + (7 * frameMS.header.sense_node + 1) + * frameMS.header.force_node; +#else + size += (res * sizeof(short) + 2) * 2; +#endif + /* set res to OK because if getMSFrame + * is successful res = number of words + * read + */ + res = OK; + print_frame_short( + "MS frame =", + array1dTo2d_short( + frameMS.node_data, + frameMS.node_data_size, + frameMS.header. + sense_node), + frameMS.header.force_node, + frameMS.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + /*read self raw*/ + case 0x15: + if (numberParameters > 1) { + pr_info("Get 1 SS Frame\n"); + setScanMode(SCAN_MODE_LOCKED, typeOfCommand[1]); + mdelay(WAIT_FOR_FRESH_FRAMES); + setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + flushFIFO(); + /* delete the events related to some touch + * (allow to call this function while touching + * the screen without having a flooding of the + * FIFO) */ + res = getSSFrame3(SS_RAW, &frameSS); + + if (res < OK) { + pr_err("Error while taking the SS frame... ERROR %08X\n", + res); + } else { + pr_info("The frame size is %d words\n", + res); +#ifdef RAW_DATA_FORMAT_DEC + size += 3 * 2 + 5 + + (frameSS.header.sense_node + + frameSS.header.force_node) * 7; +#else + size += (res * sizeof(short) + 2) * 2; +#endif + /* set res to OK because if getMSFrame + * is successful res = number of words + * read + */ + res = OK; + print_frame_short( + "SS force frame =", + array1dTo2d_short( + frameSS.force_data, + frameSS.header. + force_node, 1), + frameSS.header.force_node, 1); + print_frame_short( + "SS sense frame =", + array1dTo2d_short( + frameSS.sense_data, + frameSS.header. + sense_node, + frameSS.header. + sense_node), + 1, frameSS.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + + break; + + case 0x14: /* read mutual comp data */ + pr_info("Get MS Compensation Data\n"); + res = readMutualSenseCompensationData(LOAD_CX_MS_TOUCH, + &compData); + + if (res < 0) + pr_err("Error reading MS compensation data ERROR %08X\n", + res); + else { + pr_info("MS Compensation Data Reading Finished!\n"); + size += ((compData.node_data_size + 3) * + sizeof(u8)) * 2; + print_frame_i8("MS Data (Cx2) =", + array1dTo2d_i8( + compData.node_data, + compData. + node_data_size, + compData.header. + sense_node), + compData.header.force_node, + compData.header.sense_node); + } + break; + + case 0x16: /* read self comp data */ + pr_info("Get SS Compensation Data...\n"); + res = readSelfSenseCompensationData(LOAD_CX_SS_TOUCH, + &comData); + if (res < 0) + pr_err("Error reading SS compensation data ERROR %08X\n", + res); + else { + pr_info("SS Compensation Data Reading Finished!\n"); + size += ((comData.header.force_node + + comData.header.sense_node) * 2 + 6) * + sizeof(u8) * 2; + print_frame_u8("SS Data Ix2_fm = ", + array1dTo2d_u8(comData.ix2_fm, + comData.header. + force_node, 1), + comData.header.force_node, 1); + print_frame_i8("SS Data Cx2_fm = ", + array1dTo2d_i8(comData.cx2_fm, + comData.header. + force_node, 1), + comData.header.force_node, 1); + print_frame_u8("SS Data Ix2_sn = ", + array1dTo2d_u8(comData.ix2_sn, + comData.header. + sense_node, + comData.header. + sense_node), 1, + comData.header.sense_node); + print_frame_i8("SS Data Cx2_sn = ", + array1dTo2d_i8(comData.cx2_sn, + comData.header. + sense_node, + comData.header. + sense_node), 1, + comData.header.sense_node); + } + break; + case 0x17: /* Read mutual strength */ + pr_info("Get 1 MS Strength\n"); + setScanMode(SCAN_MODE_ACTIVE, 0xFF); + msleep(WAIT_FOR_FRESH_FRAMES); + setScanMode(SCAN_MODE_ACTIVE, 0x00); + msleep(WAIT_AFTER_SENSEOFF); + /* Flush outstanding touch events */ + flushFIFO(); + nodes = getMSFrame3(MS_STRENGTH, &frameMS); + if (nodes < 0) { + res = nodes; + pr_err("Error while taking the MS strength... ERROR %08X\n", + res); + } else { + pr_info("The frame size is %d words\n", nodes); +#ifdef RAW_DATA_FORMAT_DEC + size += 3 * 2 + + (7 * frameMS.header.sense_node + 1) + * frameMS.header.force_node; +#else + size += (nodes * sizeof(short) + 2) * 2; +#endif + print_frame_short("MS strength =", + array1dTo2d_short(frameMS.node_data, + frameMS.node_data_size, + frameMS.header.sense_node), + frameMS.header.force_node, + frameMS.header.sense_node); + res = OK; + } + break; + case 0x03: /* MS Raw DATA TEST */ + res = fts_system_reset(); + if (res >= OK) + res = production_test_ms_raw(LIMITS_FILE, 1, + &tests); + break; + + case 0x04: /* MS CX DATA TEST */ + res = fts_system_reset(); + if (res >= OK) + res = production_test_ms_cx(LIMITS_FILE, 1, + &tests); + break; + + case 0x05: /* SS RAW DATA TEST */ + res = fts_system_reset(); + if (res >= OK) + res = production_test_ss_raw(LIMITS_FILE, 1, + &tests); + break; + + case 0x06: /* SS IX CX DATA TEST */ + res = fts_system_reset(); + if (res >= OK) + res = production_test_ss_ix_cx(LIMITS_FILE, 1, + &tests); + break; + + + case 0xF0: + case 0xF1: /* TOUCH ENABLE/DISABLE */ + doClean = (int)(typeOfCommand[0] & 0x01); + res = cleanUp(doClean); + break; + + default: + pr_err("CMD(%02X) NOT VALID!! Insert a proper value\n", + typeOfCommand[0]); + res = ERROR_OP_NOT_ALLOW; + break; + } + + doClean = fts_mode_handler(info, 1); + if (typeOfCommand[0] != 0xF0) + doClean |= fts_enableInterrupt(); + if (doClean < 0) + pr_err("%s: ERROR %08X\n", __func__, + (doClean | ERROR_ENABLE_INTER)); + } else { + pr_err("NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n"); + res = ERROR_OP_NOT_ALLOW; + } + +END: + /* here start the reporting phase, assembling the data + * to send in the file node */ + size = PAGE_SIZE; + index = 0; + index += scnprintf(all_strbuff + index, size - index, "{ %08X", res); + + if (res >= OK) { + /*all the other cases are already fine printing only the res.*/ + switch (typeOfCommand[0]) { + case 0x13: + case 0x17: +#ifdef RAW_DATA_FORMAT_DEC + index += scnprintf(all_strbuff + index, size - index, + "%3d", + (u8)frameMS.header.force_node); + index += scnprintf(all_strbuff + index, size - index, + "%3d", + (u8)frameMS.header.sense_node); +#else + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (u8)frameMS.header.force_node); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (u8)frameMS.header.sense_node); +#endif + + for (j = 0; j < frameMS.node_data_size; j++) { +#ifdef RAW_DATA_FORMAT_DEC + if (j % frameMS.header.sense_node == 0) + index += scnprintf(all_strbuff + index, + size - index, "\n"); + index += scnprintf(all_strbuff + index, + size - index, "%7d", + frameMS.node_data[j]); +#else + index += scnprintf(all_strbuff + index, + size - index, + "%02X%02X", + (frameMS.node_data[j] & 0xFF00) >> 8, + frameMS.node_data[j] & 0xFF); +#endif + } + + kfree(frameMS.node_data); + break; + + case 0x15: +#ifdef RAW_DATA_FORMAT_DEC + index += scnprintf(all_strbuff + index, size - index, + "%3d", + (u8)frameSS.header.force_node); + index += scnprintf(all_strbuff + index, size - index, + "%3d", + (u8)frameSS.header.sense_node); + index += scnprintf(all_strbuff + index, size - index, + "\n"); +#else + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (u8)frameSS.header.force_node); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (u8)frameSS.header.sense_node); +#endif + + /* Copying self raw data Force */ + for (j = 0; j < frameSS.header.force_node; j++) { +#ifdef RAW_DATA_FORMAT_DEC + index += scnprintf(all_strbuff + index, + size - index, + "%7d", + frameSS.force_data[j]); +#else + index += scnprintf(all_strbuff + index, + size - index, + "%02X%02X", + (frameSS.force_data[j] & 0xFF00) >> 8, + frameSS.force_data[j] & 0xFF); +#endif + } + + + +#ifdef RAW_DATA_FORMAT_DEC + index += scnprintf(all_strbuff + index, size - index, + "\n"); +#endif + + /* Copying self raw data Sense */ + for (j = 0; j < frameSS.header.sense_node; j++) { +#ifdef RAW_DATA_FORMAT_DEC + index += scnprintf(all_strbuff + index, + size - index, "%7d", + frameSS.sense_data[j]); +#else + index += scnprintf(all_strbuff + index, + size - index, + "%02X%02X", + (frameSS.sense_data[j] & 0xFF00) >> 8, + frameSS.sense_data[j] & 0xFF); +#endif + } + + kfree(frameSS.force_data); + kfree(frameSS.sense_data); + break; + + case 0x14: + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (u8)compData.header.force_node); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (u8)compData.header.sense_node); + + /* Cpying CX1 value */ + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (compData.cx1) & 0xFF); + + /* Copying CX2 values */ + for (j = 0; j < compData.node_data_size; j++) { + index += scnprintf(all_strbuff + index, + size - index, + "%02X", + (compData.node_data[j]) & 0xFF); + } + + kfree(compData.node_data); + break; + + case 0x16: + index += scnprintf(all_strbuff + index, + size - index, "%02X", + comData.header.force_node); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + comData.header.sense_node); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (comData.f_ix1) & 0xFF); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (comData.s_ix1) & 0xFF); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (comData.f_cx1) & 0xFF); + + index += scnprintf(all_strbuff + index, + size - index, "%02X", + (comData.s_cx1) & 0xFF); + + /* Copying IX2 Force */ + for (j = 0; j < comData.header.force_node; j++) { + index += scnprintf(all_strbuff + index, + size - index, + "%02X", + comData.ix2_fm[j] & 0xFF); + } + + /* Copying IX2 Sense */ + for (j = 0; j < comData.header.sense_node; j++) { + index += scnprintf(all_strbuff + index, + size - index, + "%02X", + comData.ix2_sn[j] & 0xFF); + } + + /* Copying CX2 Force */ + for (j = 0; j < comData.header.force_node; j++) { + index += scnprintf(all_strbuff + index, + size - index, + "%02X", + comData.cx2_fm[j] & 0xFF); + } + + /* Copying CX2 Sense */ + for (j = 0; j < comData.header.sense_node; j++) { + index += scnprintf(all_strbuff + index, + size - index, + "%02X", + comData.cx2_sn[j] & 0xFF); + } + + kfree(comData.ix2_fm); + kfree(comData.ix2_sn); + kfree(comData.cx2_fm); + kfree(comData.cx2_sn); + break; + + default: + break; + } + } + + index += scnprintf(all_strbuff + index, size - index, " }\n"); + numberParameters = 0; + /* need to reset the number of parameters in order to wait the + * next command, comment if you want to repeat the last command sent + * just doing a cat */ + /* pr_err("numberParameters = %d\n", numberParameters); */ + + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + mutex_unlock(&info->diag_cmd_lock); + + return index; +} + +static DEVICE_ATTR(fwupdate, 0664, fts_fwupdate_show, + fts_fwupdate_store); +static DEVICE_ATTR(appid, 0444, fts_appid_show, NULL); +static DEVICE_ATTR(mode_active, 0444, fts_mode_active_show, NULL); +static DEVICE_ATTR(fw_file_test, 0444, fts_fw_test_show, NULL); +static DEVICE_ATTR(status, 0444, fts_status_show, NULL); +static DEVICE_ATTR(stm_fts_cmd, 0664, stm_fts_cmd_show, + stm_fts_cmd_store); +#ifdef USE_ONE_FILE_NODE +static DEVICE_ATTR(feature_enable, 0664, + fts_feature_enable_show, fts_feature_enable_store); +#else + + +#ifdef GRIP_MODE +static DEVICE_ATTR(grip_mode, 0664, fts_grip_mode_show, + fts_grip_mode_store); +#endif + +#ifdef CHARGER_MODE +static DEVICE_ATTR(charger_mode, 0664, + fts_charger_mode_show, fts_charger_mode_store); +#endif + +#ifdef GLOVE_MODE +static DEVICE_ATTR(glove_mode, 0664, + fts_glove_mode_show, fts_glove_mode_store); +#endif + +#ifdef COVER_MODE +static DEVICE_ATTR(cover_mode, 0664, + fts_cover_mode_show, fts_cover_mode_store); +#endif + +#ifdef STYLUS_MODE +static DEVICE_ATTR(stylus_mode, 0664, + fts_stylus_mode_show, fts_stylus_mode_store); +#endif + +#endif + +#ifdef GESTURE_MODE +static DEVICE_ATTR(gesture_mask, 0664, + fts_gesture_mask_show, fts_gesture_mask_store); +static DEVICE_ATTR(gesture_coordinates, 0664, + fts_gesture_coordinates_show, NULL); +#endif + +static DEVICE_ATTR(touchsim, 0664, + fts_touch_simulation_show, + fts_touch_simulation_store); + +/* /sys/devices/soc.0/f9928000.i2c/i2c-6/6-0049 */ +static struct attribute *fts_attr_group[] = { + &dev_attr_fwupdate.attr, + &dev_attr_appid.attr, + &dev_attr_mode_active.attr, + &dev_attr_fw_file_test.attr, + &dev_attr_status.attr, + &dev_attr_stm_fts_cmd.attr, +#ifdef USE_ONE_FILE_NODE + &dev_attr_feature_enable.attr, +#else + +#ifdef GRIP_MODE + &dev_attr_grip_mode.attr, +#endif +#ifdef CHARGER_MODE + &dev_attr_charger_mode.attr, +#endif +#ifdef GLOVE_MODE + &dev_attr_glove_mode.attr, +#endif +#ifdef COVER_MODE + &dev_attr_cover_mode.attr, +#endif +#ifdef STYLUS_MODE + &dev_attr_stylus_mode.attr, +#endif + +#endif + +#ifdef GESTURE_MODE + &dev_attr_gesture_mask.attr, + &dev_attr_gesture_coordinates.attr, +#endif + &dev_attr_touchsim.attr, + NULL, +}; + +/** @}*/ +/** @}*/ + + +/** + * @defgroup isr Interrupt Service Routine (Event Handler) + * The most important part of the driver is the ISR (Interrupt Service Routine) + * called also as Event Handler \n + * As soon as the interrupt pin goes low, fts_interrupt_handler() is called and + * the chain to read and parse the event read from the FIFO start.\n + * For any different kind of EVT_ID there is a specific event handler + * which will take the correct action to report the proper info to the host. \n + * The most important events are the one related to touch information, status + * update or user report. + * @{ + */ + +/** + * Report to the linux input system the pressure and release of a button + * handling concurrency + * @param info pointer to fts_ts_info which contains info about the device + * and its hw setup + * @param key_code button value + */ +void fts_input_report_key(struct fts_ts_info *info, int key_code) +{ + mutex_lock(&info->input_report_mutex); + input_report_key(info->input_dev, key_code, 1); + input_sync(info->input_dev); + input_report_key(info->input_dev, key_code, 0); + input_sync(info->input_dev); + mutex_unlock(&info->input_report_mutex); +} + + + +/** + * Event Handler for no events (EVT_ID_NOEVENT) + */ +static bool fts_nop_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + pr_info("%s: Doing nothing for event = %02X %02X %02X %02X %02X %02X %02X %02X\n", + __func__, event[0], event[1], event[2], event[3], + event[4], + event[5], event[6], event[7]); + return false; +} + +/** + * Event handler for enter and motion events (EVT_ID_ENTER_POINT, + * EVT_ID_MOTION_POINT ) + * report touch coordinates and additional information + * to the linux input system + */ +static bool fts_enter_pointer_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + unsigned char touchId; + unsigned int touch_condition = 1, tool = MT_TOOL_FINGER; + int x, y, z, major, minor, distance; + u8 touchType; + + if (!info->resume_bit) + goto no_report; + + touchType = event[1] & 0x0F; + touchId = (event[1] & 0xF0) >> 4; + + x = (((int)event[3] & 0x0F) << 8) | (event[2]); + y = ((int)event[4] << 4) | ((event[3] & 0xF0) >> 4); + z = (int)event[5]; + if (z <= 0) { + /* Should not happen, because zero pressure implies contact has + * left, so this function should not be invoked. For safety, to + * prevent this touch from being dropped, set to smallest + * pressure value instead + */ + pr_err("%s: Pressure is %i, but pointer is not leaving\n", + __func__, z); + z = 1; /* smallest non-zero pressure value */ + } + major = (int)(((event[0] & 0x0C) << 2) | ((event[6] & 0xF0) >> 4)); + minor = (int)(((event[7] & 0xC0) >> 2) | (event[6] & 0x0F)); + /* TODO: check with fw how they will report distance */ + distance = 0; /* if the tool is touching the display + * the distance should be 0 */ + + if (x == info->board->x_axis_max) + x--; + + if (y == info->board->y_axis_max) + y--; + + input_mt_slot(info->input_dev, touchId); + switch (touchType) { +#ifdef STYLUS_MODE + case TOUCH_TYPE_STYLUS: + pr_info("%s : It is a stylus!\n", __func__); + if (info->stylus_enabled == 1) { + /* if stylus_enabled is not ==1 + * it will be reported as normal touch */ + tool = MT_TOOL_PEN; + touch_condition = 1; + __set_bit(touchId, &info->stylus_id); + break; + } +#endif + /* TODO: customer can implement a different strategy for each kind of + * touch */ + case TOUCH_TYPE_FINGER: + case TOUCH_TYPE_GLOVE: + case TOUCH_TYPE_PALM: + pr_debug("%s : It is a touch type %d!\n", __func__, touchType); + tool = MT_TOOL_FINGER; + touch_condition = 1; + __set_bit(touchId, &info->touch_id); + break; + + + case TOUCH_TYPE_HOVER: + tool = MT_TOOL_FINGER; + touch_condition = 0; /* need to hover */ + z = 0; /* no pressure */ + __set_bit(touchId, &info->touch_id); + distance = DISTANCE_MAX;/* check with fw report the hovering + * distance */ + break; + + case TOUCH_TYPE_INVALID: + default: + pr_err("%s : Invalid touch type = %d ! No Report...\n", + __func__, touchType); + goto no_report; + } + + input_report_key(info->input_dev, BTN_TOUCH, touch_condition); + input_mt_report_slot_state(info->input_dev, tool, 1); + + /* pr_info("%s : TouchID = %d,Touchcount = %d\n", __func__, + * touchId,touchcount); */ + + input_report_abs(info->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, major); + input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, minor); + input_report_abs(info->input_dev, ABS_MT_PRESSURE, z); + +#ifndef SKIP_DISTANCE + input_report_abs(info->input_dev, ABS_MT_DISTANCE, distance); +#endif + /* pr_info("%s : Event 0x%02x - ID[%d], (x, y) = (%3d, %3d) + * Size = %d\n", + * __func__, *event, touchId, x, y, touchType); */ + + return true; +no_report: + return false; +} + +/** + * Event handler for leave event (EVT_ID_LEAVE_POINT ) + * Report to the linux input system that one touch left the display + */ +static bool fts_leave_pointer_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + unsigned char touchId; + unsigned int tool = MT_TOOL_FINGER; + u8 touchType; + + touchType = event[1] & 0x0F; + touchId = (event[1] & 0xF0) >> 4; + + input_mt_slot(info->input_dev, touchId); + + input_report_abs(info->input_dev, ABS_MT_PRESSURE, 0); + switch (touchType) { +#ifdef STYLUS_MODE + case TOUCH_TYPE_STYLUS: + pr_info("%s : It is a stylus!\n", __func__); + if (info->stylus_enabled == 1) { + /* if stylus_enabled is not ==1 it will be reported as + * normal touch */ + tool = MT_TOOL_PEN; + __clear_bit(touchId, &info->stylus_id); + break; + } +#endif + + case TOUCH_TYPE_FINGER: + /* pr_info("%s : It is a finger!\n", __func__); */ + case TOUCH_TYPE_GLOVE: + /* pr_info("%s : It is a glove!\n", __func__); */ + case TOUCH_TYPE_PALM: + /* pr_info("%s : It is a palm!\n", __func__); */ + case TOUCH_TYPE_HOVER: + tool = MT_TOOL_FINGER; + __clear_bit(touchId, &info->touch_id); + break; + + case TOUCH_TYPE_INVALID: + default: + pr_err("%s : Invalid touch type = %d ! No Report...\n", + __func__, touchType); + return false; + } + + input_mt_report_slot_state(info->input_dev, tool, 0); + + /* pr_info("%s : TouchID = %d, Touchcount = %d\n", __func__, + * touchId,touchcount); */ + + + input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, -1); + /* pr_info("%s : Event 0x%02x - release ID[%d]\n", __func__, + * event[0], touchId); */ + return true; +} + +/* EventId : EVT_ID_MOTION_POINT */ +#define fts_motion_pointer_event_handler fts_enter_pointer_event_handler +/* remap the motion event handler to the same function which handle the enter + * event */ + +/** + * Event handler for error events (EVT_ID_ERROR) + * Handle unexpected error events implementing recovery strategy and + * restoring the sensing status that the IC had before the error occurred + */ +static bool fts_error_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + int error = 0; + + pr_info("%s: Received event %02X %02X %02X %02X %02X %02X %02X %02X\n", + __func__, event[0], event[1], event[2], event[3], event[4], + event[5], + event[6], event[7]); + + switch (event[1]) { + case EVT_TYPE_ERROR_ESD:/* esd */ + {/* before reset clear all slot */ + release_all_touches(info); + + fts_chip_powercycle(info); + + error = fts_system_reset(); + error |= fts_mode_handler(info, 0); + error |= fts_enableInterrupt(); + if (error < OK) + pr_err("%s Cannot restore the device ERROR %08X\n", + __func__, error); + } + break; + case EVT_TYPE_ERROR_WATCHDOG: /* watch dog timer */ + { + dumpErrorInfo(NULL, 0); + /* before reset clear all slots */ + release_all_touches(info); + error = fts_system_reset(); + error |= fts_mode_handler(info, 0); + error |= fts_enableInterrupt(); + if (error < OK) + pr_err("%s Cannot reset the device ERROR %08X\n", + __func__, error); + } + break; + } + return false; +} + +/** + * Event handler for controller ready event (EVT_ID_CONTROLLER_READY) + * Handle controller events received after unexpected reset of the IC updating + * the resets flag and restoring the proper sensing status + */ +static bool fts_controller_ready_event_handler(struct fts_ts_info *info, + unsigned char *event) +{ + int error; + + pr_info("%s: Received event %02X %02X %02X %02X %02X %02X %02X %02X\n", + __func__, event[0], event[1], event[2], event[3], event[4], + event[5], event[6], event[7]); + release_all_touches(info); + setSystemResetedUp(1); + setSystemResetedDown(1); + error = fts_mode_handler(info, 0); + if (error < OK) + pr_err("%s Cannot restore the device status ERROR %08X\n", + __func__, error); + return false; +} + +/** + * Event handler for status events (EVT_ID_STATUS_UPDATE) + * Handle status update events + */ +static bool fts_status_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + switch (event[1]) { + case EVT_TYPE_STATUS_ECHO: + pr_debug("%s: Echo event of command = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], event[5], + event[6], event[7]); + break; + + case EVT_TYPE_STATUS_FORCE_CAL: + switch (event[2]) { + case 0x00: + pr_info("%s: Continuous frame drop Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x01: + pr_info("%s: Mutual negative detect Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x02: + pr_info("%s: Mutual calib deviation Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x11: + pr_info("%s: SS negative detect Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x12: + pr_info("%s: SS negative detect Force cal in Low Power mode = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x13: + pr_info("%s: SS negative detect Force cal in Idle mode = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x20: + pr_info("%s: SS invalid Mutual Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x21: + pr_info("%s: SS invalid Self Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x22: + pr_info("%s: SS invalid Self Island soft Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x30: + pr_info("%s: MS invalid Mutual Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x31: + pr_info("%s: MS invalid Self Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + default: + pr_info("%s: Force cal = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + } + break; + + case EVT_TYPE_STATUS_FRAME_DROP: + switch (event[2]) { + case 0x01: + pr_info("%s: Frame drop noisy frame = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x02: + pr_info("%s: Frame drop bad R = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case 0x03: + pr_info("%s: Frame drop invalid processing state = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + default: + pr_info("%s: Frame drop = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + } + break; + + case EVT_TYPE_STATUS_SS_RAW_SAT: + if (event[2] == 1) + pr_info("%s: SS Raw Saturated = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + else + pr_info("%s: SS Raw No more Saturated = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + case EVT_TYPE_STATUS_WATER: + if (event[2] == 1) + pr_info("%s: Enter Water mode = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + else + pr_info("%s: Exit Water mode = %02X %02X %02X %02X %02X %02X\n", + __func__, event[2], event[3], event[4], + event[5], event[6], event[7]); + break; + + default: + pr_err("%s: Received unhandled status event = %02X %02X %02X %02X %02X %02X %02X %02X\n", + __func__, event[0], event[1], event[2], event[3], + event[4], event[5], event[6], event[7]); + break; + } + return false; +} + + +/* key events reported in the user report */ +#ifdef PHONE_KEY +/* TODO: the customer should handle the events coming from the keys according + * his needs + * (this is just an sample code that report the click of a button after a + * press->release action) */ +/** + * Event handler for status events (EVT_TYPE_USER_KEY) + * Handle keys update events, the third byte of the event is a bitmask, + * if the bit set means that the corresponding key is pressed. + */ +static void fts_key_event_handler(struct fts_ts_info *info, + unsigned char *event) +{ + /* int value; */ + pr_info("%s: Received event %02X %02X %02X %02X %02X %02X %02X %02X\n", + __func__, event[0], event[1], event[2], event[3], event[4], + event[5], event[6], event[7]); + + if (event[0] == EVT_ID_USER_REPORT && event[1] == EVT_TYPE_USER_KEY) { + /* event[2] contain the bitmask of the keys that are actually + * pressed */ + + if ((event[2] & FTS_KEY_0) == 0 && (key_mask & FTS_KEY_0) > 0) { + pr_info("%s: Button HOME pressed and released!\n", + __func__); + fts_input_report_key(info, KEY_HOMEPAGE); + } + + if ((event[2] & FTS_KEY_1) == 0 && (key_mask & FTS_KEY_1) > 0) { + pr_info("%s: Button Back pressed and released!\n", + __func__); + fts_input_report_key(info, KEY_BACK); + } + + if ((event[2] & FTS_KEY_2) == 0 && (key_mask & FTS_KEY_2) > 0) { + pr_info("%s: Button Menu pressed!\n", __func__); + fts_input_report_key(info, KEY_MENU); + } + + key_mask = event[2]; + } else + pr_err("%s: Invalid event passed as argument!\n", __func__); +} +#endif + +/* gesture event must be handled in the user event handler */ +#ifdef GESTURE_MODE +/* TODO: Customer should implement their own actions in respond of a gesture + * event. + * This is an example that simply print the gesture received and simulate + * the click on a different button for each gesture. */ +/** + * Event handler for gesture events (EVT_TYPE_USER_GESTURE) + * Handle gesture events and simulate the click on a different button + * for any gesture detected (@link gesture_opt Gesture IDs @endlink) + */ +static void fts_gesture_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + int value; + int needCoords = 0; + + pr_info("gesture event data: %02X %02X %02X %02X %02X %02X %02X %02X\n", + event[0], event[1], event[2], event[3], event[4], + event[5], event[6], event[7]); + + if (event[0] == EVT_ID_USER_REPORT && event[1] == + EVT_TYPE_USER_GESTURE) { + needCoords = 1; + /* default read the coordinates for all gestures excluding + * double tap */ + + switch (event[2]) { + case GEST_ID_DBLTAP: + value = KEY_WAKEUP; + pr_info("%s: double tap !\n", __func__); + needCoords = 0; + break; + + case GEST_ID_AT: + value = KEY_WWW; + pr_info("%s: @ !\n", __func__); + break; + + case GEST_ID_C: + value = KEY_C; + pr_info("%s: C !\n", __func__); + break; + + case GEST_ID_E: + value = KEY_E; + pr_info("%s: e !\n", __func__); + break; + + case GEST_ID_F: + value = KEY_F; + pr_info("%s: F !\n", __func__); + break; + + case GEST_ID_L: + value = KEY_L; + pr_info("%s: L !\n", __func__); + break; + + case GEST_ID_M: + value = KEY_M; + pr_info("%s: M !\n", __func__); + break; + + case GEST_ID_O: + value = KEY_O; + pr_info("%s: O !\n", __func__); + break; + + case GEST_ID_S: + value = KEY_S; + pr_info("%s: S !\n", __func__); + break; + + case GEST_ID_V: + value = KEY_V; + pr_info("%s: V !\n", __func__); + break; + + case GEST_ID_W: + value = KEY_W; + pr_info("%s: W !\n", __func__); + break; + + case GEST_ID_Z: + value = KEY_Z; + pr_info("%s: Z !\n", __func__); + break; + + case GEST_ID_RIGHT_1F: + value = KEY_RIGHT; + pr_info("%s: -> !\n", __func__); + break; + + case GEST_ID_LEFT_1F: + value = KEY_LEFT; + pr_info("%s: <- !\n", __func__); + break; + + case GEST_ID_UP_1F: + value = KEY_UP; + pr_info("%s: UP !\n", __func__); + break; + + case GEST_ID_DOWN_1F: + value = KEY_DOWN; + pr_info("%s: DOWN !\n", __func__); + break; + + case GEST_ID_CARET: + value = KEY_APOSTROPHE; + pr_info("%s: ^ !\n", __func__); + break; + + case GEST_ID_LEFTBRACE: + value = KEY_LEFTBRACE; + pr_info("%s: < !\n", __func__); + break; + + case GEST_ID_RIGHTBRACE: + value = KEY_RIGHTBRACE; + pr_info("%s: > !\n", __func__); + break; + + default: + pr_err("%s: No valid GestureID!\n", __func__); + goto gesture_done; + } + + if (needCoords == 1) + readGestureCoords(event); + + fts_input_report_key(info, value); + +gesture_done: + return; + } else + pr_err("%s: Invalid event passed as argument!\n", __func__); +} +#endif + + +/** + * Event handler for user report events (EVT_ID_USER_REPORT) + * Handle user events reported by the FW due to some interaction triggered + * by an external user (press keys, perform gestures, etc.) + */ +static bool fts_user_report_event_handler(struct fts_ts_info *info, unsigned + char *event) +{ + switch (event[1]) { +#ifdef PHONE_KEY + case EVT_TYPE_USER_KEY: + fts_key_event_handler(info, event); + break; +#endif + + case EVT_TYPE_USER_PROXIMITY: + if (event[2] == 0) + pr_err("%s No proximity!\n", __func__); + else + pr_err("%s Proximity Detected!\n", __func__); + break; + +#ifdef GESTURE_MODE + case EVT_TYPE_USER_GESTURE: + fts_gesture_event_handler(info, event); + break; +#endif + default: + pr_err("%s: Received unhandled user report event = %02X %02X %02X %02X %02X %02X %02X %02X\n", + __func__, event[0], event[1], event[2], event[3], + event[4], event[5], event[6], event[7]); + break; + } + return false; +} + +#if 0 // no heatmap support + +static void heatmap_enable(void) +{ + unsigned char command[] = {0xA4, 0x06, LOCAL_HEATMAP_MODE}; + fts_write(command, 3); +} + +static bool read_heatmap_raw(struct v4l2_heatmap *v4l2, strength_t *data) +{ + unsigned char heatmap_read_command[] = {0xA6, 0x00, 0x00}; + + unsigned int num_elements; + /* index for looping through the heatmap buffer read over the bus */ + unsigned int local_i; + + int result; + + /* old value of the counter, for comparison */ + static uint16_t counter; + + strength_t heatmap_value; + /* final position of the heatmap value in the full heatmap frame */ + unsigned int frame_i; + + int heatmap_x, heatmap_y; + int max_x = v4l2->format.width; + int max_y = v4l2->format.height; + + struct heatmap_report report = {0}; + + result = fts_writeRead(heatmap_read_command, 3, + (uint8_t *) &report, sizeof(report)); + if (result != OK) { + pr_err("%s: i2c read failed, fts_writeRead returned %i", + __func__, result); + return false; + } + if (report.mode != LOCAL_HEATMAP_MODE) { + pr_err("Touch IC not in local heatmap mode: %X %X %i", + report.prefix, report.mode, report.counter); + return false; + } + + le16_to_cpus(&report.counter); /* enforce little-endian order */ + if (report.counter == counter && counter != 0) { + /* + * We shouldn't make ordered comparisons because of + * potential overflow, but at least the value + * should have changed. If the value remains the same, + * but we are processing a new interrupt, + * this could indicate slowness in the interrupt handler. + */ + pr_warn("Heatmap frame has stale counter value %i", + counter); + } + counter = report.counter; + num_elements = report.size_x * report.size_y; + if (num_elements > LOCAL_HEATMAP_WIDTH * LOCAL_HEATMAP_HEIGHT) { + pr_err("Unexpected heatmap size: %i x %i", + report.size_x, report.size_y); + return false; + } + + /* set all to zero, will only write to non-zero locations in the loop */ + memset(data, 0, max_x * max_y * sizeof(data[0])); + /* populate the data buffer, rearranging into final locations */ + for (local_i = 0; local_i < num_elements; local_i++) { + /* enforce little-endian order */ + le16_to_cpus(&report.data[local_i]); + heatmap_value = report.data[local_i]; + + if (heatmap_value == 0) { + /* Already set to zero. Nothing to do */ + continue; + } + + heatmap_x = report.offset_x + (local_i % report.size_x); + heatmap_y = report.offset_y + (local_i / report.size_x); + + if (heatmap_x < 0 || heatmap_x >= max_x || + heatmap_y < 0 || heatmap_y >= max_y) { + pr_err("Invalid x or y: (%i, %i), value=%i, ending loop\n", + heatmap_x, heatmap_y, heatmap_value); + return false; + } + frame_i = heatmap_y * max_x + heatmap_x; + data[frame_i] = heatmap_value; + } + return true; +} +#endif // no heat map + +/** + * Bottom Half Interrupt Handler function + * This handler is called each time there is at least one new event in the FIFO + * and the interrupt pin of the IC goes low. It will read all the events from + * the FIFO and dispatch them to the proper event handler according the event + * ID + */ +static irqreturn_t fts_interrupt_handler(int irq, void *handle) +{ + struct fts_ts_info *info = handle; + int error = 0, count = 0; + unsigned char regAdd = FIFO_CMD_READALL; + unsigned char data[FIFO_EVENT_SIZE * FIFO_DEPTH]; + unsigned char eventId; + const unsigned char EVENTS_REMAINING_POS = 7; + const unsigned char EVENTS_REMAINING_MASK = 0x1F; + unsigned char events_remaining = 0; + unsigned char *evt_data; + + /* It is possible that interrupts were disabled while the handler is + * executing, before acquiring the mutex. If so, simply return. + */ + if (fts_set_bus_ref(info, FTS_BUS_REF_IRQ, true) < 0) { + fts_set_bus_ref(info, FTS_BUS_REF_IRQ, false); + return IRQ_HANDLED; + } + + /* prevent CPU from entering deep sleep */ + cpu_latency_qos_update_request(&info->pm_qos_req, 100); + + __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ)); + + /* Read the first FIFO event and the number of events remaining */ + error = fts_writeReadU8UX(regAdd, 0, 0, data, FIFO_EVENT_SIZE, + DUMMY_FIFO); + events_remaining = data[EVENTS_REMAINING_POS] & EVENTS_REMAINING_MASK; + events_remaining = (events_remaining > FIFO_DEPTH - 1) ? + FIFO_DEPTH - 1 : events_remaining; + + /* Drain the rest of the FIFO, up to 31 events */ + if (error == OK && events_remaining > 0) { + error = fts_writeReadU8UX(regAdd, 0, 0, &data[FIFO_EVENT_SIZE], + FIFO_EVENT_SIZE * events_remaining, + DUMMY_FIFO); + } + if (error != OK) { + pr_err("Error (%08X) while reading from FIFO in fts_event_handler\n", + error); + } else { + for (count = 0; count < events_remaining + 1; count++) { + evt_data = &data[count * FIFO_EVENT_SIZE]; + + if (evt_data[0] == EVT_ID_NOEVENT) + break; + + eventId = evt_data[0] >> 4; + + /* Ensure event ID is within bounds */ + if (eventId < NUM_EVT_ID) + info->event_dispatch_table[eventId](info, + evt_data); + } + } + + if (info->touch_id == 0) + input_report_key(info->input_dev, BTN_TOUCH, 0); + + input_sync(info->input_dev); + + cpu_latency_qos_update_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE); + fts_set_bus_ref(info, FTS_BUS_REF_IRQ, false); + return IRQ_HANDLED; +} +/** @}*/ + + + +/** + * Implement the fw update and initialization flow of the IC that should + * be executed at every boot up. The function perform a fw update of the + * IC in case of crc error or a new fw version and then understand if the + * IC need to be re-initialized again. + * + * @return OK if success or an error code which specify the type of error + * encountered + */ +static int fts_fw_update(struct fts_ts_info *info) +{ + u8 error_to_search[4] = { EVT_TYPE_ERROR_CRC_CX_HEAD, + EVT_TYPE_ERROR_CRC_CX, + EVT_TYPE_ERROR_CRC_CX_SUB_HEAD, + EVT_TYPE_ERROR_CRC_CX_SUB }; + int ret = 0; + int init_type = NO_INIT; + +#ifdef PRE_SAVED_METHOD + int keep_cx = 1; +#else + int keep_cx = 0; +#endif + + + pr_info("Fw Auto Update is starting...\n"); + + /* Check CRC status */ + ret = fts_crc_check(); + if (ret > OK) { + pr_err("%s: CRC Error or NO FW!\n", __func__); + info->reflash_fw = 1; + } else { + pr_info("%s: NO CRC Error or Impossible to read CRC register!\n", + __func__); + } + ret = flashProcedure(info->board->fw_name, info->reflash_fw, keep_cx); + if ((ret & 0xF000000F) == ERROR_FILE_NOT_FOUND) { + pr_err("%s: firmware file not found. Bypassing update.\n", + __func__); + ret = 0; + goto out; + } else if ((ret & 0xFF000000) == ERROR_FLASH_PROCEDURE) { + pr_err("%s: firmware update failed; retrying. ERROR %08X\n", + __func__, ret); + /* Power cycle the touch IC */ + fts_chip_powercycle(info); + ret = flashProcedure(info->board->fw_name, info->reflash_fw, + keep_cx); + if ((ret & 0xFF000000) == ERROR_FLASH_PROCEDURE) { + pr_err("%s: firmware update failed again! ERROR %08X\n", + __func__, ret); + pr_err("Fw Auto Update Failed!\n"); + return ret; + } + } + info->reflash_fw = 0; + + pr_info("%s: Verifying if CX CRC Error...\n", __func__); + ret = fts_system_reset(); + if (ret >= OK) { + ret = pollForErrorType(error_to_search, 4); + if (ret < OK) { + pr_info("%s: No Cx CRC Error Found!\n", __func__); + pr_info("%s: Verifying if Panel CRC Error...\n", + __func__); + error_to_search[0] = EVT_TYPE_ERROR_CRC_PANEL_HEAD; + error_to_search[1] = EVT_TYPE_ERROR_CRC_PANEL; + ret = pollForErrorType(error_to_search, 2); + if (ret < OK) { + pr_info("%s: No Panel CRC Error Found!\n", + __func__); + init_type = NO_INIT; + } else { + pr_err("%s: Panel CRC Error FOUND! CRC ERROR = %02X\n", + __func__, ret); + init_type = SPECIAL_PANEL_INIT; + } + } else { + pr_err("%s: Cx CRC Error FOUND! CRC ERROR = %02X\n", + __func__, ret); + + /** This path of the code is used only in case there is + * a CRC error in code or config which not allow the fw + * to compute the CRC in the CX before + */ + pr_info("%s: Try to recovery with CX in fw file...\n", + __func__); + ret = flashProcedure(info->board->fw_name, CRC_CX, 0); + pr_info("%s: Refresh panel init data", __func__); + } + } else { + /* Skip initialization because the real state is unknown */ + pr_err("%s: Error while executing system reset! ERROR %08X\n", + __func__, ret); + } + + if (init_type == NO_INIT) { +#ifdef PRE_SAVED_METHOD + if (systemInfo.u8_cfgAfeVer != systemInfo.u8_cxAfeVer) { + init_type = SPECIAL_FULL_PANEL_INIT; + pr_err("%s: Different CX AFE Ver: %02X != %02X... Execute FULL Panel Init!\n", + __func__, systemInfo.u8_cfgAfeVer, + systemInfo.u8_cxAfeVer); + } else +#endif + if (systemInfo.u8_cfgAfeVer != systemInfo.u8_panelCfgAfeVer) { + init_type = SPECIAL_PANEL_INIT; + pr_err("%s: Different Panel AFE Ver: %02X != %02X... Execute Panel Init!\n", + __func__, systemInfo.u8_cfgAfeVer, + systemInfo.u8_panelCfgAfeVer); + } else + init_type = NO_INIT; + } + +out: + /** Reinitialize after a complete FW update or if the initialization + * status is not correct. + */ + if (init_type != NO_INIT) { + ret = fts_chip_initialization(info, init_type); + if (ret < OK) { + pr_err("%s: Cannot initialize the chip ERROR %08X\n", + __func__, ret); + } + + /* Reset after initialization */ + ret = fts_system_reset(); + if (ret < OK) { + pr_err("%s: Reset failed, ERROR %08X\n", __func__, + ret); + } + } + + ret = fts_init_sensing(info); + if (ret < OK) { + pr_err("Cannot initialize the hardware device ERROR %08X\n", + ret); + } + + pr_err("Fw Update Finished! error = %08X\n", ret); + return ret; +} + +#ifndef FW_UPDATE_ON_PROBE +/** + * Function called by the delayed workthread executed after the probe in + * order to perform the fw update flow + * @see fts_fw_update() + */ +static void fts_fw_update_auto(struct work_struct *work) +{ + struct delayed_work *fwu_work = container_of(work, struct delayed_work, + work); + struct fts_ts_info *info = container_of(fwu_work, struct fts_ts_info, + fwu_work); + + fts_set_bus_ref(info, FTS_BUS_REF_FW_UPDATE, true); + fts_fw_update(info); + fts_set_bus_ref(info, FTS_BUS_REF_FW_UPDATE, false); +} +#endif + +/* TODO: define if need to do the full mp at the boot */ +/** + * Execute the initialization of the IC (supporting a retry mechanism), + * checking also the resulting data + * @see production_test_main() + */ +static int fts_chip_initialization(struct fts_ts_info *info, int init_type) +{ + int ret2 = 0; + int retry; + int initretrycnt = 0; + + /* initialization error, retry initialization */ + for (retry = 0; retry <= RETRY_INIT_BOOT; retry++) { + ret2 = production_test_initialization(init_type); + if (ret2 == OK) + break; + initretrycnt++; + pr_err("initialization cycle count = %04d - ERROR %08X\n", + initretrycnt, ret2); + fts_chip_powercycle(info); + } + + if (ret2 < OK) /* initialization error */ + pr_err("fts initialization failed 3 times\n"); + + + return ret2; +} + + +static irqreturn_t fts_isr(int irq, void *handle) +{ + struct fts_ts_info *info = handle; + + info->timestamp = ktime_get(); + input_set_timestamp(info->input_dev, info->timestamp); + + return IRQ_WAKE_THREAD; +} + +/** + * Initialize the dispatch table with the event handlers for any possible event + * ID + * Set IRQ pin behavior (level triggered low) + * Register top half interrupt handler function. + * @see fts_interrupt_handler() + */ +static int fts_interrupt_install(struct fts_ts_info *info) +{ + int i, error = 0; + + info->event_dispatch_table = kzalloc(sizeof(event_dispatch_handler_t) * + NUM_EVT_ID, GFP_KERNEL); + + if (!info->event_dispatch_table) { + pr_err("OOM allocating event dispatch table\n"); + return -ENOMEM; + } + + for (i = 0; i < NUM_EVT_ID; i++) + info->event_dispatch_table[i] = fts_nop_event_handler; + + install_handler(info, ENTER_POINT, enter_pointer); + install_handler(info, LEAVE_POINT, leave_pointer); + install_handler(info, MOTION_POINT, motion_pointer); + install_handler(info, ERROR, error); + install_handler(info, CONTROLLER_READY, controller_ready); + install_handler(info, STATUS_UPDATE, status); + install_handler(info, USER_REPORT, user_report); + + /* disable interrupts in any case */ + error = fts_disableInterrupt(); + if (error) { + return error; + } + + error = request_threaded_irq(info->client->irq, fts_isr, + fts_interrupt_handler, IRQF_ONESHOT | IRQF_TRIGGER_LOW, + FTS_TS_DRV_NAME, info); + + if (error) { + pr_err("Request irq failed\n"); + kfree(info->event_dispatch_table); + } + + return error; +} + +/** + * Clean the dispatch table and the free the IRQ. + * This function is called when the driver need to be removed + */ +static void fts_interrupt_uninstall(struct fts_ts_info *info) +{ + fts_disableInterrupt(); + + kfree(info->event_dispatch_table); + + free_irq(info->client->irq, info); +} + +/**@}*/ + +/** + * This function try to attempt to communicate with the IC for the first time + * during the boot up process in order to read the necessary info for the + * following stages. + * The function execute a system reset, read fundamental info (system info) + * @return OK if success or an error code which specify the type of error + */ +static int fts_init(struct fts_ts_info *info) +{ + int error; + + + error = fts_system_reset(); + if (error < OK && isI2cError(error)) { + pr_err("Cannot reset the device! ERROR %08X\n", error); + return error; + } else { + if (error == (ERROR_TIMEOUT | ERROR_SYSTEM_RESET_FAIL)) { + pr_err("Setting default Sys INFO!\n"); + error = defaultSysInfo(0); + } else { + error = readSysInfo(0); /* system reset OK */ + if (error < OK) { + if (!isI2cError(error)) + error = OK; + pr_err("Cannot read Sys Info! ERROR %08X\n", + error); + } + } + } + + return error; +} + +/** + * Execute a power cycle in the IC, toggling the power lines (AVDD and DVDD) + * @param info pointer to fts_ts_info struct which contain information of the + * regulators + * @return 0 if success or another value if fail + */ +int fts_chip_powercycle(struct fts_ts_info *info) +{ + int error = 0; + + pr_info("%s: Power Cycle Starting...\n", __func__); + pr_info("%s: Disabling IRQ...\n", __func__); + /** if IRQ pin is short with DVDD a call to the ISR will triggered when + * the regulator is turned off if IRQ not disabled */ + fts_disableInterrupt(); + + if (info->vdd_reg) { + error = regulator_disable(info->vdd_reg); + if (error < 0) + pr_err("%s: Failed to disable DVDD regulator\n", + __func__); + } + + if (info->avdd_reg) { + error = regulator_disable(info->avdd_reg); + if (error < 0) + pr_err("%s: Failed to disable AVDD regulator\n", + __func__); + } + + if (info->board->reset_gpio != GPIO_NOT_DEFINED) + gpio_set_value(info->board->reset_gpio, 0); + else + mdelay(300); + + /* in FTI power up first the digital and then the analog */ + if (info->vdd_reg) { + error = regulator_enable(info->vdd_reg); + if (error < 0) + pr_err("%s: Failed to enable DVDD regulator\n", + __func__); + } + + mdelay(1); + + if (info->avdd_reg) { + error = regulator_enable(info->avdd_reg); + if (error < 0) + pr_err("%s: Failed to enable AVDD regulator\n", + __func__); + } + + mdelay(5); /* time needed by the regulators for reaching the regime + * values */ + + + if (info->board->reset_gpio != GPIO_NOT_DEFINED) { + mdelay(10); /* time to wait before bring up the reset + * gpio after the power up of the regulators */ + gpio_set_value(info->board->reset_gpio, 1); + } + + release_all_touches(info); + + pr_info("%s: Power Cycle Finished! ERROR CODE = %08x\n", + __func__, error); + setSystemResetedUp(1); + setSystemResetedDown(1); + return error; +} + + +/** + * Complete the boot up process, initializing the sensing of the IC according + * to the current setting chosen by the host + * Register the notifier for the suspend/resume actions and the event handler + * @return OK if success or an error code which specify the type of error + */ +static int fts_init_sensing(struct fts_ts_info *info) +{ + int error = 0; + + error |= fts_mode_handler(info, 0); /* enable the features and + * sensing */ + /* error |= fts_enableInterrupt(); */ /* enable the interrupt */ + error |= fts_resetDisableIrqCount(); + + if (error < OK) + pr_err("%s Init after Probe error (ERROR = %08X)\n", + __func__, error); + + return error; +} + +/* TODO: change this function according with the needs of customer in terms + * of feature to enable/disable */ + +/** + * @ingroup mode_section + * @{ + */ +/** + * The function handle the switching of the mode in the IC enabling/disabling + * the sensing and the features set from the host + * @param info pointer to fts_ts_info which contains info about the device and + * its hw setup + * @param force if 1, the enabling/disabling command will be send even + * if the feature was already enabled/disabled otherwise it will judge if + * the feature changed status or the IC had a system reset + * @return OK if success or an error code which specify the type of error + */ +static int fts_mode_handler(struct fts_ts_info *info, int force) +{ + int res = OK; + int ret = OK; + u8 settings[4] = { 0 }; + + /* disable irq wake because resuming from gesture mode */ + if (IS_POWER_MODE(info->mode, SCAN_MODE_LOW_POWER) && + (info->resume_bit == 1)) + disable_irq_wake(info->client->irq); + + info->mode = MODE_NOTHING; /* initialize the mode to nothing + * in order to be updated depending + * on the features enabled */ + + pr_debug("%s: Mode Handler starting...\n", __func__); + switch (info->resume_bit) { + case 0: /* screen down */ + pr_debug("%s: Screen OFF...\n", __func__); + /* do sense off in order to avoid the flooding of the fifo with + * touch events if someone is touching the panel during suspend + **/ + pr_info("%s: Sense OFF!\n", __func__); + /* for speed reason (no need to check echo in this case and + * interrupt can be enabled) */ + ret = setScanMode(SCAN_MODE_ACTIVE, 0x00); + res |= ret; /* to avoid warning unsused ret variable when a + * ll the features are disabled */ + +#ifdef GESTURE_MODE + if (info->gesture_enabled == 1) { + pr_info("%s: enter in gesture mode !\n", + __func__); + res = enterGestureMode(isSystemResettedDown()); + if (res >= OK) { + enable_irq_wake(info->client->irq); + fromIDtoMask(FEAT_SEL_GESTURE, + (u8 *)&info->mode, + sizeof(info->mode)); + MODE_LOW_POWER(info->mode, 0); + } else + pr_err("%s: enterGestureMode failed! ERROR %08X recovery in senseOff...\n", + __func__, res); + } +#endif + + setSystemResetedDown(0); + break; + + case 1: /* screen up */ + pr_debug("%s: Screen ON...\n", __func__); + +#ifdef GLOVE_MODE + if ((info->glove_enabled == FEAT_ENABLE && + isSystemResettedUp()) || force == 1) { + pr_info("%s: Glove Mode setting...\n", __func__); + settings[0] = info->glove_enabled; + /* required to satisfy also the disable case */ + ret = setFeatures(FEAT_SEL_GLOVE, settings, 1); + if (ret < OK) + pr_err("%s: error during setting GLOVE_MODE! ERROR %08X\n", + __func__, ret); + res |= ret; + + if (ret >= OK && info->glove_enabled == FEAT_ENABLE) { + fromIDtoMask(FEAT_SEL_GLOVE, (u8 *)&info->mode, + sizeof(info->mode)); + pr_info("%s: GLOVE_MODE Enabled!\n", __func__); + } else + pr_info("%s: GLOVE_MODE Disabled!\n", __func__); + } + +#endif + +#ifdef COVER_MODE + if ((info->cover_enabled == FEAT_ENABLE && + isSystemResettedUp()) || force == 1) { + pr_info("%s: Cover Mode setting...\n", __func__); + settings[0] = info->cover_enabled; + ret = setFeatures(FEAT_SEL_COVER, settings, 1); + if (ret < OK) + pr_err("%s: error during setting COVER_MODE! ERROR %08X\n", + __func__, ret); + res |= ret; + + if (ret >= OK && info->cover_enabled == FEAT_ENABLE) { + fromIDtoMask(FEAT_SEL_COVER, (u8 *)&info->mode, + sizeof(info->mode)); + pr_info("%s: COVER_MODE Enabled!\n", __func__); + } else + pr_info("%s: COVER_MODE Disabled!\n", __func__); + } +#endif +#ifdef CHARGER_MODE + if ((info->charger_enabled > 0 && isSystemResettedUp()) || + force == 1) { + pr_info("%s: Charger Mode setting...\n", __func__); + + settings[0] = info->charger_enabled; + ret = setFeatures(FEAT_SEL_CHARGER, settings, 1); + if (ret < OK) + pr_err("%s: error during setting CHARGER_MODE! ERROR %08X\n", + __func__, ret); + res |= ret; + + if (ret >= OK && info->charger_enabled == FEAT_ENABLE) { + fromIDtoMask(FEAT_SEL_CHARGER, + (u8 *)&info->mode, + sizeof(info->mode)); + pr_info("%s: CHARGER_MODE Enabled!\n", + __func__); + } else + pr_info("%s: CHARGER_MODE Disabled!\n", + __func__); + } +#endif + + +#ifdef GRIP_MODE + if ((info->grip_enabled == FEAT_ENABLE && + isSystemResettedUp()) || force == 1) { + pr_info("%s: Grip Mode setting...\n", __func__); + settings[0] = info->grip_enabled; + ret = setFeatures(FEAT_SEL_GRIP, settings, 1); + if (ret < OK) + pr_err("%s: error during setting GRIP_MODE! ERROR %08X\n", + __func__, ret); + res |= ret; + + if (ret >= OK && info->grip_enabled == FEAT_ENABLE) { + fromIDtoMask(FEAT_SEL_GRIP, (u8 *)&info->mode, + sizeof(info->mode)); + pr_info("%s: GRIP_MODE Enabled!\n", __func__); + } else + pr_info("%s: GRIP_MODE Disabled!\n", __func__); + } +#endif + /* If some selective scan want to be enabled can be done + * an or of the following options + */ + /* settings[0] = ACTIVE_MULTI_TOUCH | ACTIVE_KEY | */ + /* ACTIVE_HOVER | ACTIVE_PROXIMITY | */ + /* ACTIVE_FORCE; */ + settings[0] = 0xFF; /* enable all the possible scans mode + * supported by the config */ + pr_info("%s: Sense ON!\n", __func__); + res |= setScanMode(SCAN_MODE_ACTIVE, settings[0]); + info->mode |= (SCAN_MODE_ACTIVE << 24); + MODE_ACTIVE(info->mode, settings[0]); + + + setSystemResetedUp(0); + break; + + default: + pr_err("%s: invalid resume_bit value = %d! ERROR %08X\n", + __func__, info->resume_bit, ERROR_OP_NOT_ALLOW); + res = ERROR_OP_NOT_ALLOW; + } + + + pr_debug("%s: Mode Handler finished! res = %08X mode = %08X\n", + __func__, res, info->mode); + return res; +} + +/** + * Configure the switch GPIO to toggle bus master between AP and SLPI. + * gpio_value takes one of + * { FTS_SWITCH_GPIO_VALUE_SLPI_MASTER, FTS_SWITCH_GPIO_VALUE_AP_MASTER } + */ +static void fts_set_switch_gpio(struct fts_ts_info *info, int gpio_value) +{ + int retval; + unsigned int gpio = info->board->switch_gpio; + + if (!gpio_is_valid(gpio)) + return; + + pr_debug("%s: toggling i2c switch to %s\n", __func__, + gpio_value == FTS_SWITCH_GPIO_VALUE_AP_MASTER ? "AP" : "SLPI"); + + retval = gpio_direction_output(gpio, gpio_value); + if (retval < 0) + pr_err("%s: Failed to toggle switch_gpio, err = %d\n", + __func__, retval); +} + +/** + * Resume work function which perform a system reset, clean all the touches + * from the linux input system and prepare the ground for enabling the sensing + */ +static void fts_resume_work(struct work_struct *work) +{ + struct fts_ts_info *info; + + info = container_of(work, struct fts_ts_info, resume_work); + + if (!info->sensor_sleep) + return; + +#ifdef CONFIG_TOUCHSCREEN_TBN + if (info->tbn) + tbn_request_bus(info->tbn); +#endif + + fts_set_switch_gpio(info, FTS_SWITCH_GPIO_VALUE_AP_MASTER); + + __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ)); + + info->resume_bit = 1; + + fts_system_reset(); + + release_all_touches(info); + + fts_mode_handler(info, 0); + + info->sensor_sleep = false; + + fts_enableInterrupt(); + + complete_all(&info->bus_resumed); +} + +/** + * Suspend work function which clean all the touches from Linux input system + * and prepare the ground to disabling the sensing or enter in gesture mode + */ +static void fts_suspend_work(struct work_struct *work) +{ + struct fts_ts_info *info; + + info = container_of(work, struct fts_ts_info, suspend_work); + + if (info->sensor_sleep) + return; + + reinit_completion(&info->bus_resumed); + + __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ)); + + info->resume_bit = 0; + + fts_mode_handler(info, 0); + + release_all_touches(info); + + info->sensor_sleep = true; + + fts_disableInterrupt(); + + fts_set_switch_gpio(info, FTS_SWITCH_GPIO_VALUE_SLPI_MASTER); + +#ifdef CONFIG_TOUCHSCREEN_TBN + if (info->tbn) + tbn_release_bus(info->tbn); +#endif +} +/** @}*/ + + +static void fts_aggregate_bus_state(struct fts_ts_info *info) +{ + pr_debug("%s: bus_refmask = 0x%02X.\n", __func__, + info->bus_refmask); + + /* Complete or cancel any outstanding transitions */ + cancel_work_sync(&info->suspend_work); + cancel_work_sync(&info->resume_work); + + if ((info->bus_refmask == 0 && info->sensor_sleep) || + (info->bus_refmask != 0 && !info->sensor_sleep)) + return; + + if (info->bus_refmask == 0) + queue_work(info->event_wq, &info->suspend_work); + else + queue_work(info->event_wq, &info->resume_work); +} + +int fts_set_bus_ref(struct fts_ts_info *info, u16 ref, bool enable) +{ + int result = OK; + + mutex_lock(&info->bus_mutex); + + if ((enable && (info->bus_refmask & ref)) || + (!enable && !(info->bus_refmask & ref))) { + pr_err("%s: reference is unexpectedly set: mask=0x%04X, ref=0x%04X, enable=%d.\n", + __func__, info->bus_refmask, ref, enable); + mutex_unlock(&info->bus_mutex); + return ERROR_OP_NOT_ALLOW; + } + + if (enable) { + /* IRQs can only keep the bus active. IRQs received while the + * bus is transferred to SLPI should be ignored. + */ + if (ref == FTS_BUS_REF_IRQ && info->bus_refmask == 0) + result = ERROR_OP_NOT_ALLOW; + else + info->bus_refmask |= ref; + } else + info->bus_refmask &= ~ref; + fts_aggregate_bus_state(info); + + mutex_unlock(&info->bus_mutex); + + /* When triggering a wake, wait up to one second to resume. SCREEN_ON + * and IRQ references do not need to wait. + */ + if (enable && ref != FTS_BUS_REF_SCREEN_ON && ref != FTS_BUS_REF_IRQ) { + wait_for_completion_timeout(&info->bus_resumed, HZ); + if (info->sensor_sleep) { + pr_err("%s: Failed to wake the touch bus: mask=0x%04X, ref=0x%04X, enable=%d.\n", + __func__, info->bus_refmask, ref, enable); + result = ERROR_TIMEOUT; + } + } + + return result; +} + +#if 0 +/** + * Callback function used to detect the suspend/resume events generated by + * clicking the power button. + * This function schedule a suspend or resume work according to the event + * received. + */ +static int fts_screen_state_chg_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct fts_ts_info *info = container_of(nb, struct fts_ts_info, + notifier); + struct msm_drm_notifier *evdata = data; + unsigned int blank; + + if (val != MSM_DRM_EVENT_BLANK && val != MSM_DRM_EARLY_EVENT_BLANK) + return NOTIFY_DONE; + + if (!info || !evdata || !evdata->data) { + pr_info("%s: Bad fts notifier call!\n", __func__); + return NOTIFY_DONE; + } + + pr_debug("%s: fts notifier begin!\n", __func__); + + /* finish processing any events on queue */ + flush_workqueue(info->event_wq); + + blank = *(int *) (evdata->data); + switch (blank) { + case MSM_DRM_BLANK_POWERDOWN: + case MSM_DRM_BLANK_LP: + if (val == MSM_DRM_EARLY_EVENT_BLANK) { + pr_info("%s: BLANK\n", __func__); + fts_set_bus_ref(info, FTS_BUS_REF_SCREEN_ON, false); + } + break; + case MSM_DRM_BLANK_UNBLANK: + if (val == MSM_DRM_EVENT_BLANK) { + pr_info("%s: UNBLANK\n", __func__); + fts_set_bus_ref(info, FTS_BUS_REF_SCREEN_ON, true); + } + break; + } + return NOTIFY_OK; +} + +static struct notifier_block fts_noti_block = { + .notifier_call = fts_screen_state_chg_callback, +}; +#endif + +/** + * From the name of the power regulator get/put the actual regulator structs + * (copying their references into fts_ts_info variable) + * @param info pointer to fts_ts_info which contains info about the device and + * its hw setup + * @param get if 1, the regulators are get otherwise they are put (released) + * back to the system + * @return OK if success or an error code which specify the type of error + */ +static int fts_get_reg(struct fts_ts_info *info, bool get) +{ + int retval; + const struct fts_hw_platform_data *bdata = info->board; + + if (!get) { + retval = 0; + goto regulator_put; + } + + if ((bdata->vdd_reg_name != NULL) && (*bdata->vdd_reg_name != 0)) { + info->vdd_reg = regulator_get(info->dev, bdata->vdd_reg_name); + if (IS_ERR(info->vdd_reg)) { + pr_err("%s: Failed to get power regulator\n", __func__); + retval = PTR_ERR(info->vdd_reg); + goto regulator_put; + } + } + + if ((bdata->avdd_reg_name != NULL) && (*bdata->avdd_reg_name != 0)) { + info->avdd_reg = regulator_get(info->dev, bdata->avdd_reg_name); + if (IS_ERR(info->avdd_reg)) { + pr_err("%s: Failed to get bus pullup regulator\n", + __func__); + retval = PTR_ERR(info->avdd_reg); + goto regulator_put; + } + } + + return OK; + +regulator_put: + if (info->vdd_reg) { + regulator_put(info->vdd_reg); + info->vdd_reg = NULL; + } + + if (info->avdd_reg) { + regulator_put(info->avdd_reg); + info->avdd_reg = NULL; + } + + return retval; +} + + +/** + * Enable or disable the power regulators + * @param info pointer to fts_ts_info which contains info about the device and + * its hw setup + * @param enable if 1, the power regulators are turned on otherwise they are + * turned off + * @return OK if success or an error code which specify the type of error + */ +static int fts_enable_reg(struct fts_ts_info *info, bool enable) +{ + int retval; + + if (!enable) { + retval = 0; + goto disable_pwr_reg; + } + + if (info->vdd_reg) { + retval = regulator_enable(info->vdd_reg); + if (retval < 0) { + pr_err("%s: Failed to enable bus regulator\n", + __func__); + goto exit; + } + } + + if (info->avdd_reg) { + retval = regulator_enable(info->avdd_reg); + if (retval < 0) { + pr_err("%s: Failed to enable power regulator\n", + __func__); + goto disable_bus_reg; + } + } + + return OK; + +disable_pwr_reg: + if (info->avdd_reg) + regulator_disable(info->avdd_reg); + +disable_bus_reg: + if (info->vdd_reg) + regulator_disable(info->vdd_reg); + +exit: + return retval; +} + +/** + * Configure a GPIO according to the parameters + * @param gpio gpio number + * @param config if true, the gpio is set up otherwise it is free + * @param dir direction of the gpio, 0 = in, 1 = out + * @param state initial value (if the direction is in, this parameter is + * ignored) + * return error code + */ +static int fts_gpio_setup(int gpio, bool config, int dir, int state) +{ + int retval = 0; + unsigned char buf[16]; + + if (config) { + scnprintf(buf, sizeof(buf), "fts_gpio_%u\n", gpio); + + retval = gpio_request(gpio, buf); + if (retval) { + pr_err("%s: Failed to get gpio %d (code: %d)", + __func__, gpio, retval); + return retval; + } + + if (dir == 0) + retval = gpio_direction_input(gpio); + else + retval = gpio_direction_output(gpio, state); + if (retval) { + pr_err("%s: Failed to set gpio %d direction", + __func__, gpio); + return retval; + } + } else + gpio_free(gpio); + + return retval; +} + +/** + * Setup the IRQ and RESET (if present) gpios. + * If the Reset Gpio is present it will perform a cycle HIGH-LOW-HIGH in order + * to assure that the IC has been reset properly + */ +static int fts_set_gpio(struct fts_ts_info *info) +{ + int retval; + struct fts_hw_platform_data *bdata = + info->board; + + retval = fts_gpio_setup(bdata->irq_gpio, true, 0, 0); + if (retval < 0) { + pr_err("%s: Failed to configure irq GPIO\n", __func__); + goto err_gpio_irq; + } + + if (gpio_is_valid(bdata->switch_gpio)) { + retval = fts_gpio_setup(bdata->switch_gpio, true, 1, 1); + if (retval < 0) + pr_err("%s: Failed to configure I2C switch\n", + __func__); + } + + if (bdata->reset_gpio >= 0) { + retval = fts_gpio_setup(bdata->reset_gpio, true, 1, 0); + if (retval < 0) { + pr_err("%s: Failed to configure reset GPIO\n", + __func__); + goto err_gpio_reset; + } + } + if (bdata->reset_gpio >= 0) { + gpio_set_value(bdata->reset_gpio, 0); + mdelay(10); + gpio_set_value(bdata->reset_gpio, 1); + } + + return OK; + +err_gpio_reset: + fts_gpio_setup(bdata->irq_gpio, false, 0, 0); + bdata->reset_gpio = GPIO_NOT_DEFINED; +err_gpio_irq: + return retval; +} + +/** + * Retrieve and parse the hw information from the device tree node defined in + * the system. + * the most important information to obtain are: IRQ and RESET gpio numbers, + * power regulator names + * In the device file node is possible to define additional optional + * information + * that can be parsed here. + */ +static int parse_dt(struct device *dev, struct fts_hw_platform_data *bdata) +{ + int retval; + const char *name; + struct device_node *np = dev->of_node; + u32 coords[2]; + + bdata->switch_gpio = of_get_named_gpio(np, "st,switch_gpio", 0); + pr_info("switch_gpio = %d\n", bdata->switch_gpio); + + bdata->irq_gpio = of_get_named_gpio_flags(np, "st,irq-gpio", 0, NULL); + + pr_info("irq_gpio = %d\n", bdata->irq_gpio); + + + retval = of_property_read_string(np, "st,regulator_dvdd", &name); + if (retval == -EINVAL) + bdata->vdd_reg_name = NULL; + else if (retval < 0) + return retval; + else { + bdata->vdd_reg_name = name; + pr_info("pwr_reg_name = %s\n", name); + } + + retval = of_property_read_string(np, "st,regulator_avdd", &name); + if (retval == -EINVAL) + bdata->avdd_reg_name = NULL; + else if (retval < 0) + return retval; + else { + bdata->avdd_reg_name = name; + pr_info("bus_reg_name = %s\n", name); + } + + if (of_property_read_bool(np, "st,reset-gpio")) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "st,reset-gpio", 0, + NULL); + pr_info("reset_gpio =%d\n", bdata->reset_gpio); + } else + bdata->reset_gpio = GPIO_NOT_DEFINED; + + retval = of_property_read_string(np, "st,firmware_name", &name); + if (retval == -EINVAL) + bdata->fw_name = PATH_FILE_FW; + else if (retval >= 0) + bdata->fw_name = name; + pr_info("firmware name = %s\n", bdata->fw_name); + + if (of_property_read_u32_array(np, "st,max-coords", coords, 2)) { + pr_err("st,max-coords not found, using 1440x2560\n"); + coords[0] = 1440; + coords[1] = 2560; + } + bdata->x_axis_max = coords[0]; + bdata->y_axis_max = coords[1]; + + return OK; +} + +/** + * Probe function, called when the driver it is matched with a device + * with the same name compatible name + * This function allocate, initialize all the most important functions and flow + * those are used by the driver to operate with the IC. + * It allocates device variables, initialize queues and schedule works, + * registers the IRQ handler, suspend/resume callbacks, registers the device + * to the linux input subsystem etc. + */ +#ifdef I2C_INTERFACE +static int fts_probe(struct i2c_client *client, const struct i2c_device_id *idp) +{ +#else +static int fts_probe(struct spi_device *client) +{ +#endif + + struct fts_ts_info *info = NULL; + int error = 0; + struct device_node *dp = client->dev.of_node; + int retval; + int skip_5_1 = 0; + u16 bus_type; + + pr_info("%s: driver probe begin!\n", __func__); + pr_info("driver ver. %s\n", FTS_TS_DRV_VERSION); + + pr_info("SET Bus Functionality :\n"); +#ifdef I2C_INTERFACE + pr_info("I2C interface...\n"); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + pr_err("Unsupported I2C functionality\n"); + error = -EIO; + goto ProbeErrorExit_0; + } + + pr_info("i2c address: %x\n", client->addr); + bus_type = BUS_I2C; +#else + pr_info("SPI interface...\n"); + client->mode = SPI_MODE_0; +#ifndef SPI4_WIRE + client->mode |= SPI_3WIRE; +#endif + + client->max_speed_hz = SPI_CLOCK_FREQ; + client->bits_per_word = 8; + if (spi_setup(client) < 0) { + pr_err("Unsupported SPI functionality\n"); + error = -EIO; + goto ProbeErrorExit_0; + } + bus_type = BUS_SPI; +#endif + + + pr_info("SET Device driver INFO:\n"); + + + info = kzalloc(sizeof(struct fts_ts_info), GFP_KERNEL); + if (!info) { + pr_err("Out of memory... Impossible to allocate struct info!\n"); + error = -ENOMEM; + goto ProbeErrorExit_0; + } + + info->client = client; + info->dev = &info->client->dev; + + dev_set_drvdata(info->dev, info); + +#ifdef CONFIG_TOUCHSCREEN_TBN + info->tbn = tbn_init(info->dev); + if (!info->tbn) { + pr_err("ERROR: failed to init tbn context\n"); + error = -ENODEV; + goto ProbeErrorExit_1; + } +#endif + + if (dp) { + info->board = devm_kzalloc(&client->dev, + sizeof(struct fts_hw_platform_data), + GFP_KERNEL); + if (!info->board) { + pr_err("ERROR:info.board kzalloc failed\n"); + goto ProbeErrorExit_1; + } + parse_dt(&client->dev, info->board); + } + + pr_info("SET Regulators:\n"); + retval = fts_get_reg(info, true); + if (retval < 0) { + pr_err("ERROR: %s: Failed to get regulators\n", __func__); + goto ProbeErrorExit_1; + } + + retval = fts_enable_reg(info, true); + if (retval < 0) { + pr_err("%s: ERROR Failed to enable regulators\n", __func__); + goto ProbeErrorExit_2; + } + + pr_info("SET GPIOS:\n"); + retval = fts_set_gpio(info); + if (retval < 0) { + pr_err("%s: ERROR Failed to set up GPIO's\n", __func__); + goto ProbeErrorExit_2; + } + info->client->irq = gpio_to_irq(info->board->irq_gpio); + + pr_info("SET Event Handler:\n"); + + info->wakesrc = wakeup_source_create("fts_tp"); + info->event_wq = alloc_workqueue("fts-event-queue", WQ_UNBOUND | + WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1); + if (!info->event_wq) { + pr_err("ERROR: Cannot create work thread\n"); + error = -ENOMEM; + goto ProbeErrorExit_4; + } + + INIT_WORK(&info->resume_work, fts_resume_work); + INIT_WORK(&info->suspend_work, fts_suspend_work); + + init_completion(&info->bus_resumed); + complete_all(&info->bus_resumed); + + pr_info("SET Input Device Property:\n"); + info->dev = &info->client->dev; + info->input_dev = input_allocate_device(); + if (!info->input_dev) { + pr_err("ERROR: No such input device defined!\n"); + error = -ENODEV; + goto ProbeErrorExit_5; + } + info->input_dev->dev.parent = &client->dev; + info->input_dev->name = FTS_TS_DRV_NAME; + scnprintf(fts_ts_phys, sizeof(fts_ts_phys), "%s/input0", + info->input_dev->name); + info->input_dev->phys = fts_ts_phys; + info->input_dev->id.bustype = bus_type; + info->input_dev->id.vendor = 0x0001; + info->input_dev->id.product = 0x0002; + info->input_dev->id.version = 0x0100; + + __set_bit(EV_SYN, info->input_dev->evbit); + __set_bit(EV_KEY, info->input_dev->evbit); + __set_bit(EV_ABS, info->input_dev->evbit); + __set_bit(BTN_TOUCH, info->input_dev->keybit); + /* __set_bit(BTN_TOOL_FINGER, info->input_dev->keybit); */ + /* __set_bit(BTN_TOOL_PEN, info->input_dev->keybit); */ + + input_mt_init_slots(info->input_dev, TOUCH_ID_MAX, INPUT_MT_DIRECT); + + /* input_mt_init_slots(info->input_dev, TOUCH_ID_MAX); */ + + input_set_abs_params(info->input_dev, ABS_MT_POSITION_X, X_AXIS_MIN, + info->board->x_axis_max, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_POSITION_Y, Y_AXIS_MIN, + info->board->y_axis_max, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MAJOR, AREA_MIN, + AREA_MAX, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MINOR, AREA_MIN, + AREA_MAX, 0, 0); + input_set_abs_params(info->input_dev, ABS_MT_PRESSURE, PRESSURE_MIN, + PRESSURE_MAX, 0, 0); +#ifndef SKIP_DISTANCE + input_set_abs_params(info->input_dev, ABS_MT_DISTANCE, DISTANCE_MIN, + DISTANCE_MAX, 0, 0); +#endif + +#ifdef GESTURE_MODE + input_set_capability(info->input_dev, EV_KEY, KEY_WAKEUP); + + input_set_capability(info->input_dev, EV_KEY, KEY_M); + input_set_capability(info->input_dev, EV_KEY, KEY_O); + input_set_capability(info->input_dev, EV_KEY, KEY_E); + input_set_capability(info->input_dev, EV_KEY, KEY_W); + input_set_capability(info->input_dev, EV_KEY, KEY_C); + input_set_capability(info->input_dev, EV_KEY, KEY_L); + input_set_capability(info->input_dev, EV_KEY, KEY_F); + input_set_capability(info->input_dev, EV_KEY, KEY_V); + input_set_capability(info->input_dev, EV_KEY, KEY_S); + input_set_capability(info->input_dev, EV_KEY, KEY_Z); + input_set_capability(info->input_dev, EV_KEY, KEY_WWW); + + input_set_capability(info->input_dev, EV_KEY, KEY_LEFT); + input_set_capability(info->input_dev, EV_KEY, KEY_RIGHT); + input_set_capability(info->input_dev, EV_KEY, KEY_UP); + input_set_capability(info->input_dev, EV_KEY, KEY_DOWN); + + input_set_capability(info->input_dev, EV_KEY, KEY_F1); + input_set_capability(info->input_dev, EV_KEY, KEY_F2); + input_set_capability(info->input_dev, EV_KEY, KEY_F3); + input_set_capability(info->input_dev, EV_KEY, KEY_F4); + input_set_capability(info->input_dev, EV_KEY, KEY_F5); + + input_set_capability(info->input_dev, EV_KEY, KEY_LEFTBRACE); + input_set_capability(info->input_dev, EV_KEY, KEY_RIGHTBRACE); +#endif + +#ifdef PHONE_KEY + /* KEY associated to the touch screen buttons */ + input_set_capability(info->input_dev, EV_KEY, KEY_HOMEPAGE); + input_set_capability(info->input_dev, EV_KEY, KEY_BACK); + input_set_capability(info->input_dev, EV_KEY, KEY_MENU); +#endif + + mutex_init(&info->diag_cmd_lock); + + mutex_init(&(info->input_report_mutex)); + mutex_init(&info->bus_mutex); + + /* Assume screen is on throughout probe */ + info->bus_refmask = FTS_BUS_REF_SCREEN_ON; + +#ifdef GESTURE_MODE + mutex_init(&gestureMask_mutex); +#endif + + spin_lock_init(&fts_int); + + /* register the multi-touch input device */ + error = input_register_device(info->input_dev); + if (error) { + pr_err("ERROR: No such input device\n"); + error = -ENODEV; + goto ProbeErrorExit_5_1; + } + + skip_5_1 = 1; + /* track slots */ + info->touch_id = 0; +#ifdef STYLUS_MODE + info->stylus_id = 0; +#endif + + + /* init feature switches (by default all the features are disable, + * if one feature want to be enabled from the start, + * set the corresponding value to 1)*/ + info->gesture_enabled = 0; + info->glove_enabled = 0; + info->charger_enabled = 0; + info->cover_enabled = 0; + info->grip_enabled = 0; + + info->resume_bit = 1; + + /* + * This *must* be done before request_threaded_irq is called. + * Otherwise, if an interrupt is received before request is added, + * but after the interrupt has been subscribed to, pm_qos_req + * may be accessed before initialization in the interrupt handler. + */ + cpu_latency_qos_add_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE); + + pr_info("Init Core Lib:\n"); + initCore(info); + /* init hardware device */ + pr_info("Device Initialization:\n"); + error = fts_init(info); + if (error < OK) { + pr_err("Cannot initialize the device ERROR %08X\n", error); + error = -ENODEV; + goto ProbeErrorExit_6; + } + +#if defined(FW_UPDATE_ON_PROBE) && defined(FW_H_FILE) + pr_info("FW Update and Sensing Initialization:\n"); + error = fts_fw_update(info); + if (error < OK) { + pr_err("Cannot execute fw upgrade the device ERROR %08X\n", + error); + error = -ENODEV; + goto ProbeErrorExit_7; + } + +#else + pr_info("SET Auto Fw Update:\n"); + info->fwu_workqueue = alloc_workqueue("fts-fwu-queue", WQ_UNBOUND | + WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1); + if (!info->fwu_workqueue) { + pr_err("ERROR: Cannot create fwu work thread\n"); + goto ProbeErrorExit_7; + } + INIT_DELAYED_WORK(&info->fwu_work, fts_fw_update_auto); +#endif + + pr_info("SET Device File Nodes:\n"); + /* sysfs stuff */ + info->attrs.attrs = fts_attr_group; + error = sysfs_create_group(&client->dev.kobj, &info->attrs); + if (error) { + pr_err("ERROR: Cannot create sysfs structure!\n"); + error = -ENODEV; + goto ProbeErrorExit_7; + } + + error = fts_proc_init(); + if (error < OK) + pr_err("Error: can not create /proc file!\n"); + +#ifndef FW_UPDATE_ON_PROBE + queue_delayed_work(info->fwu_workqueue, &info->fwu_work, + msecs_to_jiffies(EXP_FN_WORK_DELAY_MS)); +#endif + + info->touchsim.wq = alloc_workqueue("fts-heatmap_test-queue", + WQ_UNBOUND | WQ_HIGHPRI | + WQ_CPU_INTENSIVE, 1); + + if (info->touchsim.wq) + INIT_WORK(&(info->touchsim.work), touchsim_work); + else + pr_err("ERROR: Cannot create touch sim. test work queue\n"); + + pr_info("Probe Finished!\n"); + + return OK; + + +ProbeErrorExit_7: + if(info->touchsim.wq) + destroy_workqueue(info->touchsim.wq); + +ProbeErrorExit_6: + cpu_latency_qos_remove_request(&info->pm_qos_req); + input_unregister_device(info->input_dev); + +ProbeErrorExit_5_1: + if (skip_5_1 != 1) + input_free_device(info->input_dev); + +ProbeErrorExit_5: + destroy_workqueue(info->event_wq); + +ProbeErrorExit_4: + /* destroy_workqueue(info->fwu_workqueue); */ + wakeup_source_destroy(info->wakesrc); + + fts_enable_reg(info, false); + +ProbeErrorExit_2: + fts_get_reg(info, false); + +ProbeErrorExit_1: + kfree(info); + +ProbeErrorExit_0: + pr_err("Probe Failed!\n"); + + return error; +} + + +/** + * Clear and free all the resources associated to the driver. + * This function is called when the driver need to be removed. + */ +#ifdef I2C_INTERFACE +static int fts_remove(struct i2c_client *client) +{ +#else +static int fts_remove(struct spi_device *client) +{ +#endif + + struct fts_ts_info *info = dev_get_drvdata(&(client->dev)); + + /* Force the bus active throughout removal of the client */ + fts_set_bus_ref(info, FTS_BUS_REF_FORCE_ACTIVE, true); + + pr_info("%s\n", __func__); + +#ifdef CONFIG_TOUCHSCREEN_TBN + tbn_cleanup(info->tbn); +#endif + + fts_proc_remove(); + + /* sysfs stuff */ + sysfs_remove_group(&client->dev.kobj, &info->attrs); + + /* remove interrupt and event handlers */ + fts_interrupt_uninstall(info); + + cpu_latency_qos_remove_request(&info->pm_qos_req); + + /* unregister the device */ + input_unregister_device(info->input_dev); + + /* input_free_device(info->input_dev ); */ + + /* Remove the work thread */ + destroy_workqueue(info->event_wq); + wakeup_source_destroy(info->wakesrc); + + if(info->touchsim.wq) + destroy_workqueue(info->touchsim.wq); + +#ifndef FW_UPDATE_ON_PROBE + destroy_workqueue(info->fwu_workqueue); +#endif + + fts_enable_reg(info, false); + fts_get_reg(info, false); + + /* free gpio */ + if (gpio_is_valid(info->board->irq_gpio)) + gpio_free(info->board->irq_gpio); + if (gpio_is_valid(info->board->switch_gpio)) + gpio_free(info->board->switch_gpio); + if (gpio_is_valid(info->board->reset_gpio)) + gpio_free(info->board->reset_gpio); + + /* free all */ + kfree(info); + + return OK; +} + +/** + * Struct which contains the compatible names that need to match with + * the definition of the device in the device tree node + */ +static struct of_device_id fts_of_match_table[] = { + { + .compatible = "st,fts", + }, + {}, +}; + +#ifdef I2C_INTERFACE +static const struct i2c_device_id fts_device_id[] = { + { FTS_TS_DRV_NAME, 0 }, + {} +}; + +static struct i2c_driver fts_i2c_driver = { + .driver = { + .name = FTS_TS_DRV_NAME, + .of_match_table = fts_of_match_table, + }, + .probe = fts_probe, + .remove = fts_remove, + .id_table = fts_device_id, +}; +#else +static struct spi_driver fts_spi_driver = { + .driver = { + .name = FTS_TS_DRV_NAME, + .of_match_table = fts_of_match_table, + .owner = THIS_MODULE, + }, + .probe = fts_probe, + .remove = fts_remove, +}; +#endif + + + + +static int __init fts_driver_init(void) +{ +#ifdef I2C_INTERFACE + return i2c_add_driver(&fts_i2c_driver); +#else + return spi_register_driver(&fts_spi_driver); +#endif +} + +static void __exit fts_driver_exit(void) +{ + pr_info("%s\n", __func__); +#ifdef I2C_INTERFACE + i2c_del_driver(&fts_i2c_driver); +#else + spi_unregister_driver(&fts_spi_driver); +#endif +} + + +MODULE_DESCRIPTION("STMicroelectronics MultiTouch IC Driver"); +MODULE_AUTHOR("STMicroelectronics"); +MODULE_LICENSE("GPL"); + +late_initcall(fts_driver_init); +module_exit(fts_driver_exit); diff --git a/drivers/input/touchscreen/stm/fts.h b/drivers/input/touchscreen/stm/fts.h new file mode 100644 index 000000000000..ca434c1cc9b1 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts.h @@ -0,0 +1,429 @@ +/* + * fts.h + * + * FTS Capacitive touch screen controller (FingerTipS) + * + * Copyright (C) 2017, STMicroelectronics + * Authors: AMG(Analog Mems Group) + * + * marco.cali@st.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE + * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT. + * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, + * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM + * THE + * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING + * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS. + */ + +/*! + * \file fts.h + * \brief Contains all the definitions and structs used generally by the driver + */ + +#ifndef _LINUX_FTS_I2C_H_ +#define _LINUX_FTS_I2C_H_ + +#include <linux/device.h> +#include <linux/pm_qos.h> +#include "fts_lib/ftsSoftware.h" +#include "fts_lib/ftsHardware.h" + +#ifdef CONFIG_TOUCHSCREEN_TBN +#include "../touch_bus_negotiator.h" +#endif + + +/****************** CONFIGURATION SECTION ******************/ +/** @defgroup conf_section Driver Configuration Section + * Settings of the driver code in order to suit the HW set up and the + *application behavior + * @{ + */ +/* **** CODE CONFIGURATION **** */ +#define FTS_TS_DRV_NAME "fts" /* driver name */ +#define FTS_TS_DRV_VERSION "5.2.10_Google_B1" /* driver version string + * */ +#define FTS_TS_DRV_VER 0x05020A00 /* driver version u32 format */ + +/* #define DEBUG */ /* /< define to print more logs in the kernel log + * and better follow the code flow */ +#ifdef pr_fmt +#undef pr_fmt +#define pr_fmt(fmt) "[ FTS ] " fmt +#endif + +#define DRIVER_TEST /* /< if defined allow to use and test special functions + * of the driver and fts_lib from command shell + * (useful for enginering/debug operations) */ + +/* Comment 2 flags to disable auto-tune in MP test and device boot-up */ +/* if defined allow to have some procedures at the boot or from file node to + * assure that touch works under any condition that usually are disabled in the + * MP stage of the project + */ +/* #define ENGINEERING_CODE */ +/* Initialization of CX memory allowed on the phone */ +/* #define COMPUTE_CX_ON_PHONE */ +/* #define PRE_SAVED_METHOD */ + +/*#define FW_H_FILE*/ /* include the FW data as header file */ +#ifdef FW_H_FILE +#define FW_SIZE_NAME myArray_size /* FW data array size */ +#define FW_ARRAY_NAME myArray /* FW data array name */ +/*#define FW_UPDATE_ON_PROBE*/ /* No delay updating FW */ +#endif + +#ifndef FW_UPDATE_ON_PROBE +/* Include the Production Limit File as header file, can be commented to use a + * .csv file instead */ +/* #define LIMITS_H_FILE */ +#ifdef LIMITS_H_FILE + #define LIMITS_SIZE_NAME myArray2_size /* /< name of the + * variable + * in the limits header + *file which + * specified the + *dimension of + * the limits data + *array */ + #define LIMITS_ARRAY_NAME myArray2 /* /< name of the + * variable in + * the limits header + *file which + * specified the limits + *data array */ +#endif +#else +/* if execute fw update in the probe the limit file must be a .h */ +#define LIMITS_H_FILE /* /< include the Production Limit File as header file, + * DO NOT COMMENT! */ +#define LIMITS_SIZE_NAME myArray2_size /* /< name of the + * variable + * in the limits header + *file + * which specified the + *dimension + * of the limits data + *array */ +#define LIMITS_ARRAY_NAME myArray2 /* /< name of the + * variable in the + * limits header file + *which specified + * the limits data + *array */ +#endif + +/* #define USE_ONE_FILE_NODE */ /* /< allow to enable/disable all the features + * just using one file node */ + +#ifndef FW_UPDATE_ON_PROBE +#define EXP_FN_WORK_DELAY_MS 1000 /* /< time in ms elapsed after the probe + * to start the work which execute FW + *update + * and the Initialization of the IC */ +#endif + +/* **** END **** */ + + +/* **** FEATURES USED IN THE IC **** */ +/* Enable the support of keys */ +/* #define PHONE_KEY */ + +#define GESTURE_MODE /* /< enable the support of the gestures */ +#ifdef GESTURE_MODE + #define USE_GESTURE_MASK /* /< the gestures to select are + * referred using + * a gesture bitmask instead of their + *gesture IDs */ +#endif + + +#define CHARGER_MODE /* /< enable the support to charger mode feature + * (comment to disable) */ + +#define GLOVE_MODE /* /< enable the support to glove mode feature (comment + * to disable) */ + +#define COVER_MODE /* /< enable the support to cover mode feature (comment + * to disable) */ + +#define STYLUS_MODE /* /< enable the support to stylus mode feature (comment + * to disable) */ + +#define GRIP_MODE /* /< enable the support to grip mode feature (comment + * to disable) */ + + +/* **** END **** */ + + +/* **** PANEL SPECIFICATION **** */ +#define X_AXIS_MIN 0 /* /< min X coordinate of the display */ +#define Y_AXIS_MIN 0 /* /< min Y coordinate of the display */ +#define Y_AXIS_MAX 2959 /* /< Max Y coordinate of the display */ +#define X_AXIS_MAX 1440 /* /< Max X coordinate of the display */ + +#define PRESSURE_MIN 0 /* /< min value of pressure reported */ +#define PRESSURE_MAX 127 /* /< Max value of pressure reported */ + +#define DISTANCE_MIN 0 /* /< min distance between the tool and the + * display */ +#define DISTANCE_MAX 127 /* /< Max distance between the tool and the + * display */ + +#define TOUCH_ID_MAX 10 /* /< Max number of simoultaneous touches + * reported */ + +#define AREA_MIN PRESSURE_MIN /* /< min value of Major/minor axis + * reported */ +#define AREA_MAX PRESSURE_MAX /* /< Man value of Major/minor axis + * reported */ +/* **** END **** */ + +/**@}*/ +/*********************************************************/ + +#if 0 // no heat map +/* **** LOCAL HEATMAP FEATURE *** */ +#define LOCAL_HEATMAP_WIDTH 7 +#define LOCAL_HEATMAP_HEIGHT 7 +#define LOCAL_HEATMAP_MODE 0xC1 + +struct heatmap_report { + uint8_t prefix; /* always should be 0xA0 */ + uint8_t mode; /* mode should be 0xC1 for heatmap */ + + uint16_t counter; /* LE order, should increment on each heatmap read */ + int8_t offset_x; + uint8_t size_x; + int8_t offset_y; + uint8_t size_y; + /* data is in LE order; order should be enforced after data is read */ + strength_t data[LOCAL_HEATMAP_WIDTH * LOCAL_HEATMAP_HEIGHT]; +} __attribute__((packed)); +/* **** END **** */ +#endif + +/* + * Configuration mode + * + * bitmask which can assume the value defined as features in ftsSoftware.h or + * the following values + */ + +/** @defgroup mode_section IC Status Mode + * Bitmask which keeps track of the features and working mode enabled in the + * IC. + * The meaning of the the LSB of the bitmask must be interpreted considering + * that the value defined in @link feat_opt Feature Selection Option @endlink + * correspond to the position of the corresponding bit in the mask + * @{ + */ +#define MODE_NOTHING 0x00000000 /* /< nothing enabled (sense off) */ +#define MODE_ACTIVE(_mask, _sett) \ + (_mask |= (SCAN_MODE_ACTIVE << 24) | (_sett << 16)) +/* /< store the status of scan mode active and its setting */ +#define MODE_LOW_POWER(_mask, _sett) \ + (_mask |= (SCAN_MODE_LOW_POWER << 24) | (_sett << 16)) +/* /< store the status of scan mode low power and its setting */ +#define IS_POWER_MODE(_mask, _mode) ((_mask&(_mode<<24)) != 0x00) +/* /< check the current mode of the IC */ + +/** @}*/ + +#define CMD_STR_LEN 32 /* /< max number of parameters that can accept + * the + * MP file node (stm_fts_cmd) */ + +#define TSP_BUF_SIZE PAGE_SIZE /* /< max number of bytes printable on + * the shell in the normal file nodes + **/ + + +/** + * Struct which contains information about the HW platform and set up + */ +struct fts_hw_platform_data { + int (*power) (bool on); + int switch_gpio;/* (optional) I2C switch */ + int irq_gpio; /* /< number of the gpio associated to the interrupt pin + * */ + int reset_gpio; /* /< number of the gpio associated to the reset pin */ + const char *vdd_reg_name; /* /< name of the VDD regulator */ + const char *avdd_reg_name; /* /< name of the AVDD regulator */ + const char *fw_name; + int x_axis_max; + int y_axis_max; +}; + +/* Bits for the bus reference mask */ +enum { + FTS_BUS_REF_SCREEN_ON = 0x01, + FTS_BUS_REF_IRQ = 0x02, + FTS_BUS_REF_FW_UPDATE = 0x04, + FTS_BUS_REF_SYSFS = 0x08, + FTS_BUS_REF_FORCE_ACTIVE = 0x10 +}; + +/* + * Forward declaration + */ +struct fts_ts_info; + +/* + * Dispatch event handler + * Return true if the handler has processed a pointer event + */ +typedef bool (*event_dispatch_handler_t) + (struct fts_ts_info *info, unsigned char *data); + +/** + * Driver touch simulation details + */ +struct fts_touchsim{ + /* touch simulation coordinates */ + int x, y, x_step, y_step; + + /* timer to run the touch simulation code */ + struct hrtimer hr_timer; + + struct work_struct work; + struct workqueue_struct *wq; + + /* True if the touch simulation is currently running */ + bool is_running; +}; + +/** + * FTS capacitive touch screen device information + * - dev Pointer to the structure device \n + * - client client structure \n + * - input_dev Input device structure \n + * - work Work thread \n + * - event_wq Event queue for work thread \n + * - event_dispatch_table Event dispatch table handlers \n + * - attrs SysFS attributes \n + * - mode Device operating mode (bitmask) \n + * - touch_id Bitmask for touch id (mapped to input slots) \n + * - stylus_id Bitmask for tracking the stylus touches (mapped using the + * touchId) \n + * - timer Timer when operating in polling mode \n + * - power Power on/off routine \n + * - board HW info retrieved from device tree \n + * - vdd_reg DVDD power regulator \n + * - avdd_reg AVDD power regulator \n + * - resume_bit Indicate if screen off/on \n + * - fwupdate_stat Store the result of a fw update triggered by the host \n + * - notifier Used for be notified from a suspend/resume event \n + * - sensor_sleep true suspend was called, false resume was called \n + * - wakesrc Wakeup Source struct \n + * - input_report_mutex mutex for handling the pressure of keys \n + * - series_of_switches to store the enabling status of a particular feature + * from the host \n + * - tbn Touch Bus Negotiator context + */ +struct fts_ts_info { + struct device *dev; /* Pointer to the device */ +#ifdef I2C_INTERFACE + struct i2c_client *client; /* I2C client structure */ +#else + struct spi_device *client; /* SPI client structure */ +#endif + struct input_dev *input_dev; /* Input device structure */ + + struct work_struct suspend_work; /* Suspend work thread */ + struct work_struct resume_work; /* Resume work thread */ + struct workqueue_struct *event_wq; /* Used for event handler, */ + /* suspend, resume threads */ + + struct completion bus_resumed; /* resume_work complete */ + + struct pm_qos_request pm_qos_req; + +#ifndef FW_UPDATE_ON_PROBE + struct delayed_work fwu_work; /* Work for fw update */ + struct workqueue_struct *fwu_workqueue; /* Fw update work queue */ +#endif + event_dispatch_handler_t *event_dispatch_table; /* Dispatch table */ + + struct attribute_group attrs; /* SysFS attributes */ + + unsigned int mode; /* Device operating mode */ + /* MSB - active or lpm */ + unsigned long touch_id; /* Bitmask for touch id */ +#ifdef STYLUS_MODE + unsigned long stylus_id; /* Bitmask for the stylus */ +#endif + + ktime_t timestamp; /* time that the event was first received from the + touch IC, acquired during hard interrupt, in CLOCK_MONOTONIC */ + + struct fts_hw_platform_data *board; /* HW info from device tree */ + struct regulator *vdd_reg; /* DVDD power regulator */ + struct regulator *avdd_reg; /* AVDD power regulator */ + + struct mutex bus_mutex; /* Protect access to the bus */ + unsigned int bus_refmask; /* References to the bus */ + + int resume_bit; /* Indicate if screen off/on */ + int fwupdate_stat; /* Result of a fw update */ + int reflash_fw; /* Attempt to reflash fw */ + + struct notifier_block notifier; /* Notify on suspend/resume */ + bool sensor_sleep; /* True if suspend called */ + struct wakeup_source *wakesrc; /* Wake Lock struct */ + + /* input lock */ + struct mutex input_report_mutex; /* Mutex for pressure report */ + + /* switches for features */ + int gesture_enabled; /* Gesture during suspend */ + int glove_enabled; /* Glove mode */ + int charger_enabled; /* Charger mode */ + int stylus_enabled; /* Stylus mode */ + int cover_enabled; /* Cover mode */ + int grip_enabled; /* Grip mode */ + +#ifdef CONFIG_TOUCHSCREEN_TBN + struct tbn_context *tbn; +#endif + + /* Allow only one thread to execute diag command code*/ + struct mutex diag_cmd_lock; + /* Allow one process to open procfs node */ + bool diag_node_open; + + /* Touch simulation details */ + struct fts_touchsim touchsim; + + /* Preallocated i/o read buffer */ + u8 io_read_buf[READ_CHUNK + DUMMY_FIFO]; + /* Preallocated i/o write buffer */ + u8 io_write_buf[WRITE_CHUNK + BITS_64 + DUMMY_FIFO]; + /* Preallocated i/o extra write buffer */ + u8 io_extra_write_buf[WRITE_CHUNK + BITS_64 + DUMMY_FIFO]; + +}; + +int fts_chip_powercycle(struct fts_ts_info *info); +extern int input_register_notifier_client(struct notifier_block *nb); +extern int input_unregister_notifier_client(struct notifier_block *nb); + +/* export declaration of functions in fts_proc.c */ +extern int fts_proc_init(void); +extern int fts_proc_remove(void); + +/* Bus reference tracking */ +int fts_set_bus_ref(struct fts_ts_info *info, u16 ref, bool enable); + +#endif diff --git a/drivers/input/touchscreen/stm/fts_fw.h b/drivers/input/touchscreen/stm/fts_fw.h new file mode 100644 index 000000000000..b1d7c8d5717b --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_fw.h @@ -0,0 +1,6146 @@ +#ifndef FTS_FW_V5_H +#define FTS_FW_V5_H +//This is an auto generated header file +//--->Remember to change the name of the two variables!<--- +const uint32_t myArray_size = 98168; + +const uint8_t myArray[] = { + 0x55, 0xAA, 0x55, 0xAA, 0x01, 0x00, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x74, 0x01, 0x00, + 0x60, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x13, 0x78, 0xF8, + 0x65, 0xFF, 0xBA, 0x4A, 0x34, 0x5D, 0x00, 0x00, 0x9A, 0x00, 0x45, 0xB5, 0xCB, 0xA2, 0xFF, 0xFF, + 0x00, 0x04, 0x10, 0x00, 0xE1, 0x01, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x53, 0x02, 0x00, 0x00, + 0x6D, 0x02, 0x00, 0x00, 0x87, 0x02, 0x00, 0x00, 0xA1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x43, 0x01, 0x00, + 0xFF, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x07, 0x44, 0x01, 0x00, + 0x0F, 0x44, 0x01, 0x00, 0x1D, 0x44, 0x01, 0x00, 0x2B, 0x44, 0x01, 0x00, 0x39, 0x44, 0x01, 0x00, + 0x47, 0x44, 0x01, 0x00, 0x55, 0x44, 0x01, 0x00, 0x63, 0x44, 0x01, 0x00, 0x71, 0x44, 0x01, 0x00, + 0x7F, 0x44, 0x01, 0x00, 0xC9, 0x02, 0x00, 0x00, 0x8D, 0x44, 0x01, 0x00, 0x9B, 0x44, 0x01, 0x00, + 0xA9, 0x44, 0x01, 0x00, 0xB7, 0x44, 0x01, 0x00, 0xC5, 0x44, 0x01, 0x00, 0xCD, 0x44, 0x01, 0x00, + 0xDB, 0x44, 0x01, 0x00, 0xE3, 0x44, 0x01, 0x00, 0xEB, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x01, 0x00, + 0xFB, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x32, 0x02, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF0, 0x02, 0xF8, 0x00, 0xF0, 0x68, 0xF8, 0x0A, 0xA0, 0x90, 0xE8, 0x00, 0x0C, 0x82, 0x44, + 0x83, 0x44, 0xAA, 0xF1, 0x01, 0x07, 0xDA, 0x45, 0x01, 0xD1, 0x00, 0xF0, 0x5D, 0xF8, 0xAF, 0xF2, + 0x09, 0x0E, 0xBA, 0xE8, 0x0F, 0x00, 0x13, 0xF0, 0x01, 0x0F, 0x18, 0xBF, 0xFB, 0x1A, 0x43, 0xF0, + 0x01, 0x03, 0x18, 0x47, 0x08, 0x73, 0x01, 0x00, 0x38, 0x73, 0x01, 0x00, 0x0A, 0x44, 0x4F, 0xF0, + 0x00, 0x0C, 0x10, 0xF8, 0x01, 0x3B, 0x13, 0xF0, 0x07, 0x04, 0x08, 0xBF, 0x10, 0xF8, 0x01, 0x4B, + 0x1D, 0x11, 0x08, 0xBF, 0x10, 0xF8, 0x01, 0x5B, 0x64, 0x1E, 0x05, 0xD0, 0x10, 0xF8, 0x01, 0x6B, + 0x64, 0x1E, 0x01, 0xF8, 0x01, 0x6B, 0xF9, 0xD1, 0x13, 0xF0, 0x08, 0x0F, 0x1E, 0xBF, 0x10, 0xF8, + 0x01, 0x4B, 0xAD, 0x1C, 0x0C, 0x1B, 0x09, 0xD1, 0x6D, 0x1E, 0x58, 0xBF, 0x01, 0xF8, 0x01, 0xCB, + 0xFA, 0xD5, 0x05, 0xE0, 0x14, 0xF8, 0x01, 0x6B, 0x01, 0xF8, 0x01, 0x6B, 0x6D, 0x1E, 0xF9, 0xD5, + 0x91, 0x42, 0xD6, 0xD3, 0x70, 0x47, 0x00, 0x00, 0x10, 0x3A, 0x24, 0xBF, 0x78, 0xC8, 0x78, 0xC1, + 0xFA, 0xD8, 0x52, 0x07, 0x24, 0xBF, 0x30, 0xC8, 0x30, 0xC1, 0x44, 0xBF, 0x04, 0x68, 0x0C, 0x60, + 0x70, 0x47, 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x10, 0x3A, 0x28, 0xBF, + 0x78, 0xC1, 0xFB, 0xD8, 0x52, 0x07, 0x28, 0xBF, 0x30, 0xC1, 0x48, 0xBF, 0x0B, 0x60, 0x70, 0x47, + 0x1F, 0xB5, 0x1F, 0xBD, 0x10, 0xB5, 0x10, 0xBD, 0xDF, 0xF8, 0x0C, 0xD0, 0xFF, 0xF7, 0xF8, 0xFF, + 0x14, 0xF0, 0xA2, 0xF9, 0x16, 0xF0, 0xC6, 0xFB, 0x00, 0x04, 0x10, 0x00, 0x03, 0xB4, 0xFF, 0xF7, + 0xF1, 0xFF, 0x03, 0xBC, 0x16, 0xF0, 0xC4, 0xFB, 0x40, 0xBA, 0x70, 0x47, 0xC0, 0xBA, 0x70, 0x47, + 0x12, 0x48, 0x13, 0x49, 0xA1, 0xEB, 0x00, 0x01, 0x4F, 0xF0, 0x20, 0x03, 0x91, 0xFB, 0xF3, 0xF2, + 0x02, 0xFB, 0x13, 0x11, 0x4F, 0xF0, 0xCC, 0x33, 0x4F, 0xF0, 0xCC, 0x34, 0x4F, 0xF0, 0xCC, 0x35, + 0x4F, 0xF0, 0xCC, 0x36, 0x4F, 0xF0, 0xCC, 0x37, 0x4F, 0xF0, 0xCC, 0x38, 0x4F, 0xF0, 0xCC, 0x39, + 0x4F, 0xF0, 0xCC, 0x3A, 0xA0, 0xE8, 0xF8, 0x07, 0x01, 0x3A, 0xFB, 0xD1, 0x19, 0xB1, 0x40, 0xF8, + 0x04, 0xAB, 0x04, 0x39, 0xFB, 0xD1, 0x03, 0x48, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x04, 0x10, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, + 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x01, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x10, 0xF0, + 0x0B, 0xB8, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, + 0x4F, 0xF0, 0x02, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, 0xFE, 0xBF, 0x1E, 0xF0, 0x04, 0x0F, + 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x03, 0x01, 0x4F, 0xF0, + 0x00, 0x02, 0x0F, 0xF0, 0xF1, 0xBF, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, + 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x04, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, 0xE4, 0xBF, + 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, + 0x05, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, 0xD7, 0xBF, 0x00, 0xB5, 0x14, 0xF0, 0x94, 0xF8, + 0x5D, 0xF8, 0x04, 0xEB, 0x00, 0xF0, 0x32, 0xB8, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, + 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x06, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, + 0xC3, 0xBF, 0x00, 0x00, 0x0A, 0x48, 0x4F, 0xF0, 0xFF, 0x01, 0x01, 0x70, 0x4F, 0xF0, 0x00, 0x00, + 0x80, 0xF3, 0x11, 0x88, 0x4F, 0xF0, 0x00, 0x00, 0x80, 0xF3, 0x09, 0x88, 0x05, 0x48, 0x4F, 0xF0, + 0x02, 0x01, 0x01, 0x70, 0x62, 0xB6, 0x04, 0x48, 0x4F, 0xF0, 0x80, 0x51, 0x01, 0x60, 0x70, 0x47, + 0x22, 0xED, 0x00, 0xE0, 0x18, 0x08, 0x10, 0x00, 0x04, 0xED, 0x00, 0xE0, 0x02, 0x48, 0x4F, 0xF0, + 0x80, 0x51, 0x01, 0x60, 0x70, 0x47, 0x00, 0x00, 0x04, 0xED, 0x00, 0xE0, 0x4F, 0xF0, 0x20, 0x00, + 0x80, 0xF3, 0x11, 0x88, 0xEF, 0xF3, 0x09, 0x80, 0x98, 0xB1, 0x12, 0x48, 0x00, 0x68, 0x12, 0x49, + 0x09, 0x68, 0x88, 0x42, 0x17, 0xD0, 0xEF, 0xF3, 0x09, 0x80, 0x0E, 0x49, 0x09, 0x68, 0x20, 0xE9, + 0xF0, 0x0F, 0x88, 0x60, 0x00, 0xB5, 0x0B, 0x48, 0x00, 0x68, 0x14, 0xF0, 0x6B, 0xF9, 0x5D, 0xF8, + 0x04, 0xEB, 0x08, 0x48, 0x08, 0x49, 0x0A, 0x68, 0x02, 0x60, 0x00, 0x68, 0x81, 0x68, 0xB1, 0xE8, + 0xF0, 0x0F, 0x81, 0xF3, 0x09, 0x88, 0x4E, 0xF0, 0x04, 0x0E, 0x4F, 0xF0, 0x00, 0x00, 0x80, 0xF3, + 0x11, 0x88, 0x70, 0x47, 0x1C, 0x08, 0x10, 0x00, 0x20, 0x08, 0x10, 0x00, 0xEF, 0xF3, 0x11, 0x80, + 0x4F, 0xF0, 0x20, 0x01, 0x81, 0xF3, 0x11, 0x88, 0x70, 0x47, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x00, + 0x80, 0xF3, 0x11, 0x88, 0x70, 0x47, 0x00, 0x00, 0x62, 0xB6, 0x70, 0x47, 0x72, 0xB6, 0x70, 0x47, + 0x40, 0x1E, 0xFD, 0xD1, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFD, 0x48, + 0x16, 0xF0, 0x45, 0xFA, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x14, 0xF0, 0x6B, 0xB9, + 0x38, 0xB5, 0x04, 0x46, 0xF8, 0x48, 0xF7, 0x4D, 0x20, 0x60, 0x20, 0x46, 0x13, 0xF0, 0xD3, 0xFC, + 0x00, 0x22, 0x6B, 0x46, 0x01, 0x21, 0x10, 0x46, 0x14, 0xF0, 0xA6, 0xF9, 0x01, 0x21, 0x00, 0x20, + 0x14, 0xF0, 0x85, 0xF9, 0x28, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x0F, 0xF0, 0x8C, 0xFF, 0xEC, 0xE7, + 0x38, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0xB4, 0x83, 0x82, 0x46, 0x01, 0x27, 0xD8, 0xF8, + 0x00, 0x00, 0xEB, 0x4D, 0x46, 0x46, 0x90, 0xF8, 0x31, 0x40, 0x10, 0xF8, 0x30, 0x1F, 0x90, 0xF8, + 0x31, 0x00, 0x4C, 0x43, 0x00, 0xF0, 0x03, 0x00, 0x87, 0x40, 0xA1, 0x00, 0x28, 0x46, 0x16, 0xF0, + 0x6A, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0xE5, 0xF9, + 0x00, 0x26, 0xDF, 0xF8, 0x70, 0x93, 0x12, 0xE0, 0xDA, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0xC0, 0xFF, + 0x00, 0x20, 0xD9, 0xF8, 0x08, 0x10, 0x07, 0xE0, 0x55, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, + 0x1A, 0x44, 0x45, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0xA0, 0x42, 0xF5, 0xDB, 0x76, 0x1C, 0xBE, 0x42, + 0xEA, 0xDB, 0x40, 0x46, 0x0A, 0xE0, 0x00, 0xBF, 0x02, 0x68, 0x55, 0xF8, 0x24, 0x10, 0x92, 0xF8, + 0x61, 0x20, 0x02, 0xF0, 0x03, 0x02, 0x11, 0x41, 0x2A, 0xF8, 0x14, 0x10, 0x64, 0x1E, 0xF3, 0xD2, + 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x20, 0xB3, 0x4F, 0xF0, 0x01, 0x09, + 0xC7, 0x4E, 0xDB, 0xF8, 0x00, 0x00, 0x9F, 0xB0, 0x90, 0xF8, 0x61, 0x10, 0x90, 0xF8, 0x31, 0x40, + 0xC1, 0xF3, 0x81, 0x08, 0x90, 0xF8, 0x30, 0x50, 0x09, 0xFA, 0x08, 0xFA, 0x60, 0x19, 0x81, 0x00, + 0x06, 0xEB, 0x84, 0x07, 0x30, 0x46, 0x16, 0xF0, 0x1E, 0xFA, 0xBA, 0x48, 0x34, 0x30, 0x13, 0xF0, + 0x35, 0xFC, 0xB8, 0x49, 0x34, 0x31, 0x81, 0xF8, 0x06, 0x90, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8, + 0x60, 0x20, 0x92, 0x07, 0x01, 0xD5, 0x81, 0xF8, 0x04, 0x90, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, + 0x01, 0xD0, 0x00, 0xF0, 0x8A, 0xF9, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x60, 0x00, 0xC0, 0x07, + 0x03, 0xD0, 0xAC, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0x63, 0xFF, 0x00, 0x20, 0x2B, 0xE0, 0xA9, 0x48, + 0x34, 0x30, 0xFF, 0xF7, 0x5D, 0xFF, 0xDF, 0xF8, 0x9C, 0xB2, 0x62, 0x00, 0x13, 0xA8, 0xDB, 0xF8, + 0x18, 0x10, 0x16, 0xF0, 0x4F, 0xF9, 0x6A, 0x00, 0x68, 0x46, 0xDB, 0xF8, 0x1C, 0x10, 0x16, 0xF0, + 0x49, 0xF9, 0x20, 0x46, 0x13, 0xAA, 0x06, 0xE0, 0x56, 0xF8, 0x20, 0x10, 0x32, 0xF9, 0x10, 0x30, + 0x19, 0x44, 0x46, 0xF8, 0x20, 0x10, 0x40, 0x1E, 0xF6, 0xD2, 0x28, 0x46, 0x69, 0x46, 0x06, 0xE0, + 0x57, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, 0x1A, 0x44, 0x47, 0xF8, 0x20, 0x20, 0x40, 0x1E, + 0xF6, 0xD2, 0x09, 0xF1, 0x01, 0x00, 0x81, 0x46, 0x50, 0x45, 0xD0, 0xDB, 0x95, 0x49, 0x05, 0xE0, + 0x56, 0xF8, 0x24, 0x00, 0x40, 0xFA, 0x08, 0xF0, 0x21, 0xF8, 0x14, 0x00, 0x64, 0x1E, 0xF7, 0xD2, + 0x91, 0x49, 0x05, 0xE0, 0x57, 0xF8, 0x25, 0x00, 0x40, 0xFA, 0x08, 0xF0, 0x21, 0xF8, 0x15, 0x00, + 0x6D, 0x1E, 0xF7, 0xD2, 0x1F, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xFF, 0x5F, 0xDF, 0xF8, + 0x1C, 0x82, 0x87, 0x4F, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x31, 0x40, 0x90, 0xF8, 0x30, 0x50, + 0x07, 0xEB, 0x84, 0x0A, 0x60, 0x19, 0x81, 0x00, 0x04, 0xFB, 0x05, 0xFB, 0x0A, 0xEB, 0x85, 0x06, + 0x38, 0x46, 0x16, 0xF0, 0xA0, 0xF9, 0x4F, 0xEA, 0x8B, 0x01, 0x30, 0x46, 0x16, 0xF0, 0x9B, 0xF9, + 0x78, 0x48, 0x34, 0x30, 0x13, 0xF0, 0xB2, 0xFB, 0x76, 0x48, 0x4F, 0xF0, 0x01, 0x09, 0x34, 0x30, + 0x80, 0xF8, 0x06, 0x90, 0x80, 0xF8, 0x04, 0x90, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xB0, 0x00, + 0xC0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0x09, 0xF9, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x60, 0x00, + 0xC0, 0x07, 0x03, 0xD0, 0x6B, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0xE2, 0xFE, 0xD8, 0xF8, 0x00, 0x00, + 0x90, 0xF8, 0x61, 0x00, 0xC0, 0xF3, 0x81, 0x01, 0x02, 0x91, 0x00, 0xF0, 0x03, 0x01, 0x03, 0x91, + 0x02, 0x99, 0x48, 0x46, 0x09, 0xFA, 0x01, 0xF9, 0x03, 0x99, 0x88, 0x40, 0x01, 0x90, 0x00, 0x20, + 0x31, 0xE0, 0x60, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0xCB, 0xFE, 0x5E, 0x48, 0xD0, 0xE9, 0x06, 0x32, + 0x81, 0x68, 0x20, 0x46, 0x07, 0xE0, 0x00, 0xBF, 0x57, 0xF8, 0x20, 0xC0, 0x33, 0xF9, 0x10, 0x80, + 0xC4, 0x44, 0x47, 0xF8, 0x20, 0xC0, 0x40, 0x1E, 0xF6, 0xD2, 0x28, 0x46, 0x07, 0xE0, 0x00, 0xBF, + 0x5A, 0xF8, 0x20, 0x30, 0x32, 0xF9, 0x10, 0xC0, 0x9C, 0x44, 0x4A, 0xF8, 0x20, 0xC0, 0x40, 0x1E, + 0xF6, 0xD2, 0xDD, 0xE9, 0x00, 0x02, 0x90, 0x42, 0x0B, 0xDA, 0x58, 0x46, 0x07, 0xE0, 0x00, 0xBF, + 0x56, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, 0x1A, 0x44, 0x46, 0xF8, 0x20, 0x20, 0x40, 0x1E, + 0xF6, 0xD2, 0x00, 0x98, 0x40, 0x1C, 0x00, 0x90, 0x48, 0x45, 0xCA, 0xDB, 0x01, 0x98, 0x48, 0x45, + 0x1D, 0xDD, 0x44, 0x48, 0x00, 0x21, 0x34, 0x30, 0x88, 0x46, 0x81, 0x71, 0x01, 0x99, 0xA1, 0xEB, + 0x09, 0x09, 0x12, 0xE0, 0x3F, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0x8A, 0xFE, 0x3D, 0x48, 0x81, 0x68, + 0x58, 0x46, 0x06, 0xE0, 0x56, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, 0x1A, 0x44, 0x46, 0xF8, + 0x20, 0x20, 0x40, 0x1E, 0xF6, 0xD2, 0x08, 0xF1, 0x01, 0x08, 0xC1, 0x45, 0xEA, 0xDC, 0x39, 0x49, + 0x06, 0xE0, 0x00, 0xBF, 0x57, 0xF8, 0x24, 0x00, 0x02, 0x9A, 0x10, 0x41, 0x21, 0xF8, 0x14, 0x00, + 0x64, 0x1E, 0xF7, 0xD2, 0x34, 0x49, 0x05, 0xE0, 0x5A, 0xF8, 0x25, 0x00, 0x02, 0x9A, 0x10, 0x41, + 0x21, 0xF8, 0x15, 0x00, 0x6D, 0x1E, 0xF7, 0xD2, 0x58, 0x46, 0x30, 0x4A, 0x06, 0xE0, 0x00, 0xBF, + 0x56, 0xF8, 0x20, 0x10, 0x03, 0x9B, 0x19, 0x41, 0x22, 0xF8, 0x10, 0x10, 0x40, 0x1E, 0xF7, 0xD2, + 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x00, 0x20, 0x14, 0xF0, 0x5B, 0xF8, + 0x02, 0x20, 0x14, 0xF0, 0x58, 0xF8, 0x03, 0x20, 0x14, 0xF0, 0x55, 0xF8, 0x24, 0x4E, 0x00, 0x20, + 0x30, 0x70, 0x1C, 0x48, 0x34, 0x30, 0x13, 0xF0, 0xF9, 0xFA, 0x1C, 0x48, 0x21, 0x4F, 0xDF, 0xF8, + 0x88, 0x80, 0x00, 0x68, 0x4F, 0xF0, 0x01, 0x04, 0x90, 0xF8, 0x60, 0x00, 0x80, 0x07, 0x4F, 0xEA, + 0x05, 0x70, 0x0A, 0xD5, 0x00, 0x28, 0x0F, 0xDA, 0xA8, 0x07, 0x08, 0xD5, 0x34, 0x70, 0xFF, 0xF7, + 0x14, 0xFF, 0x3C, 0x70, 0x88, 0xF8, 0x00, 0x40, 0x01, 0xE0, 0x00, 0x28, 0x04, 0xDA, 0x30, 0x78, + 0x10, 0xB9, 0xFF, 0xF7, 0x87, 0xFE, 0x3C, 0x70, 0x0A, 0x4F, 0xA8, 0x07, 0x07, 0xF1, 0x34, 0x07, + 0x26, 0xD5, 0x30, 0x78, 0x70, 0xBB, 0x38, 0x46, 0x13, 0xF0, 0xD0, 0xFA, 0x3C, 0x71, 0x0B, 0x48, + 0xFF, 0xF7, 0x2F, 0xFE, 0x09, 0x48, 0x00, 0xF0, 0x3C, 0xF8, 0x0C, 0x49, 0x08, 0x70, 0x88, 0xF8, + 0x00, 0x40, 0x1F, 0xE0, 0x38, 0x08, 0x10, 0x00, 0xB9, 0x03, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x84, 0x5A, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, 0x2E, 0x44, 0x01, 0x20, + 0x00, 0x04, 0x10, 0x00, 0x51, 0x07, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, 0x52, 0x07, 0x10, 0x00, + 0x68, 0x07, 0x07, 0xD5, 0x38, 0x48, 0x13, 0xF0, 0xA9, 0xFA, 0x04, 0x20, 0x38, 0x71, 0x37, 0x48, + 0xFF, 0xF7, 0x07, 0xFE, 0x03, 0x20, 0x14, 0xF0, 0x11, 0xF8, 0x02, 0x20, 0x14, 0xF0, 0x0E, 0xF8, + 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0x20, 0x14, 0xF0, 0x09, 0xB8, 0x31, 0x48, 0x00, 0x68, 0x90, 0xF8, + 0xB0, 0x00, 0x81, 0x07, 0x2C, 0x48, 0x01, 0xD5, 0x02, 0x21, 0x00, 0xE0, 0x01, 0x21, 0xC1, 0x72, + 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x43, 0x2A, 0x49, 0x4F, 0xF0, 0x00, 0x09, 0xCC, 0x46, 0x0F, 0x68, + 0x4B, 0x46, 0x97, 0xF8, 0x31, 0x20, 0x97, 0xF8, 0x30, 0x60, 0x97, 0xF8, 0x60, 0x40, 0x02, 0xFB, + 0x06, 0xF1, 0x09, 0xB2, 0x64, 0x07, 0x37, 0xD5, 0x22, 0x4C, 0x24, 0x68, 0x25, 0x8E, 0x8D, 0x42, + 0x32, 0xD1, 0x32, 0x34, 0x28, 0xE0, 0x35, 0x46, 0x20, 0xE0, 0x00, 0xBF, 0x34, 0xF8, 0x15, 0x10, + 0x30, 0xF8, 0x15, 0x80, 0xA1, 0xEB, 0x08, 0x01, 0x09, 0xB2, 0x00, 0x29, 0x01, 0xDB, 0x88, 0x46, + 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x08, 0xE0, 0x45, 0x07, 0xDD, 0x00, 0x29, 0x01, 0xDB, 0x8C, 0x46, + 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, + 0xB7, 0xF8, 0x63, 0x80, 0x41, 0x45, 0x01, 0xDD, 0x5B, 0x1C, 0x9B, 0xB2, 0x6D, 0x1E, 0xDD, 0xD1, + 0x04, 0xEB, 0x46, 0x04, 0x00, 0xEB, 0x46, 0x00, 0x52, 0x1E, 0xD4, 0xD2, 0x97, 0xF8, 0x65, 0x00, + 0x98, 0x42, 0x01, 0xD2, 0x4F, 0xF0, 0x01, 0x09, 0x07, 0x48, 0xA0, 0xF8, 0x00, 0xC0, 0x07, 0x48, + 0x03, 0x80, 0x48, 0x46, 0xBD, 0xE8, 0xF0, 0x83, 0x6C, 0x08, 0x10, 0x00, 0x2E, 0x44, 0x01, 0x20, + 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0x54, 0x07, 0x10, 0x00, 0x56, 0x07, 0x10, 0x00, + 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFE, 0x48, 0x15, 0xF0, 0xB1, 0xFF, 0x01, 0x21, 0xBD, 0xE8, + 0x10, 0x40, 0x00, 0x20, 0x13, 0xF0, 0xD7, 0xBE, 0x38, 0xB5, 0x04, 0x46, 0xF9, 0x48, 0x20, 0x60, + 0xF9, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x01, 0xD0, 0x01, 0x20, 0xE0, 0x72, + 0xF3, 0x4D, 0x20, 0x46, 0x13, 0xF0, 0x37, 0xFA, 0x00, 0x22, 0x6B, 0x46, 0x01, 0x21, 0x10, 0x46, + 0x13, 0xF0, 0x0A, 0xFF, 0x01, 0x21, 0x00, 0x20, 0x13, 0xF0, 0xE9, 0xFE, 0x28, 0x78, 0x00, 0x28, + 0x02, 0xD0, 0x0F, 0xF0, 0xF0, 0xFC, 0xEC, 0xE7, 0x38, 0xBD, 0x2D, 0xE9, 0xFF, 0x41, 0x00, 0x24, + 0xDD, 0xE9, 0x0A, 0x76, 0x08, 0x21, 0x68, 0x46, 0x14, 0xF0, 0x7C, 0xFC, 0x05, 0x46, 0x08, 0x21, + 0x02, 0xA8, 0x14, 0xF0, 0x77, 0xFC, 0x02, 0x46, 0x00, 0x20, 0x6F, 0xF0, 0x7E, 0x0E, 0x14, 0xE0, + 0x00, 0x21, 0x00, 0xFB, 0x02, 0xF3, 0x0D, 0xE0, 0x07, 0xEB, 0x01, 0x0C, 0x13, 0xF9, 0x0C, 0xC0, + 0xB4, 0x44, 0xF4, 0x45, 0x01, 0xDA, 0x01, 0x24, 0x03, 0xE0, 0xBC, 0xF1, 0x7F, 0x0F, 0x00, 0xDD, + 0x02, 0x24, 0x49, 0x1C, 0x91, 0x42, 0xEF, 0xDB, 0x40, 0x1C, 0xA8, 0x42, 0xE8, 0xDB, 0x20, 0x46, + 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFF, 0x41, 0x0A, 0xAC, 0x08, 0x21, 0x94, 0xE8, + 0xC0, 0x01, 0x00, 0x24, 0x68, 0x46, 0x14, 0xF0, 0x4D, 0xFC, 0x05, 0x46, 0x08, 0x21, 0x02, 0xA8, + 0x14, 0xF0, 0x48, 0xFC, 0x01, 0x46, 0x00, 0x20, 0x08, 0xE0, 0x32, 0x56, 0xD2, 0x19, 0x01, 0xD5, + 0x01, 0x24, 0x02, 0xE0, 0xFF, 0x2A, 0x00, 0xDD, 0x02, 0x24, 0x40, 0x1C, 0xA8, 0x42, 0xF4, 0xDB, + 0x00, 0x20, 0x0A, 0xE0, 0x2A, 0x18, 0xB2, 0x56, 0x12, 0xEB, 0x08, 0x02, 0x01, 0xD5, 0x01, 0x24, + 0x02, 0xE0, 0xFF, 0x2A, 0x00, 0xDD, 0x02, 0x24, 0x40, 0x1C, 0x88, 0x42, 0xF2, 0xDB, 0x20, 0x46, + 0xCE, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x13, 0xF0, 0x3F, 0xFA, 0x04, 0x46, 0x0D, 0x46, + 0x13, 0xF0, 0x3D, 0xFA, 0xDF, 0xF8, 0xE0, 0x82, 0x06, 0x46, 0x0F, 0x46, 0xD8, 0xF8, 0x00, 0x00, + 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, + 0x79, 0xFD, 0x04, 0x46, 0x0D, 0x46, 0xB0, 0x48, 0x01, 0x68, 0x91, 0xF8, 0x31, 0x80, 0x91, 0xF8, + 0x30, 0xA0, 0x01, 0x21, 0x08, 0xFB, 0x0A, 0xF0, 0x05, 0x90, 0x06, 0xA8, 0x0D, 0xF0, 0x4A, 0xFF, + 0xDF, 0xF8, 0xA8, 0x92, 0x00, 0x20, 0xDF, 0xF8, 0xA8, 0xB2, 0xD9, 0xF8, 0x00, 0x10, 0x06, 0x9B, + 0x32, 0x46, 0x91, 0xF9, 0x1B, 0x10, 0x03, 0x90, 0xCD, 0xF8, 0x00, 0xB0, 0xCD, 0xE9, 0x01, 0x31, + 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0xD4, 0xFD, 0x01, 0x20, 0x03, 0x90, 0x00, 0x21, + 0x06, 0x9B, 0xCD, 0xF8, 0x00, 0xB0, 0xCD, 0xE9, 0x01, 0x31, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, + 0x29, 0x46, 0x10, 0xF0, 0xC6, 0xFD, 0x96, 0x48, 0x34, 0x30, 0x13, 0xF0, 0x57, 0xF9, 0x94, 0x49, + 0x05, 0x20, 0x34, 0x31, 0x08, 0x71, 0x08, 0x46, 0xFF, 0xF7, 0x2E, 0xFF, 0x90, 0x48, 0x02, 0x21, + 0x80, 0x68, 0x00, 0x90, 0x04, 0xA8, 0x0D, 0xF0, 0x15, 0xFF, 0x8F, 0x48, 0x00, 0x68, 0xB0, 0xF9, + 0xC2, 0x11, 0x01, 0x91, 0xB0, 0xF9, 0xC4, 0xB1, 0x59, 0x44, 0x49, 0x10, 0x02, 0x91, 0x90, 0xF8, + 0xE8, 0x00, 0x80, 0x07, 0x0A, 0xD4, 0xAA, 0xF1, 0x01, 0x01, 0x08, 0xFB, 0x01, 0xF0, 0x05, 0x90, + 0x00, 0x99, 0x53, 0x46, 0x42, 0x46, 0x08, 0x46, 0x00, 0xF0, 0xF2, 0xFA, 0xDD, 0xE9, 0x04, 0x12, + 0x00, 0x98, 0x11, 0xF0, 0x90, 0xFA, 0x82, 0x46, 0x02, 0x21, 0x04, 0xA8, 0x0D, 0xF0, 0x55, 0xFF, + 0x01, 0x99, 0x4F, 0xF0, 0x00, 0x08, 0x8A, 0x45, 0x01, 0xDC, 0xDA, 0x45, 0x0A, 0xDA, 0x7A, 0x48, + 0x02, 0x99, 0x00, 0x68, 0xAA, 0xEB, 0x01, 0x01, 0xB0, 0xF8, 0xC6, 0x01, 0x91, 0xFB, 0xF0, 0xF0, + 0x4F, 0xFA, 0x80, 0xF8, 0x06, 0x99, 0xCD, 0xE9, 0x00, 0x18, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, + 0x29, 0x46, 0xFF, 0xF7, 0x0A, 0xFF, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, 0x21, 0xD0, 0xD9, 0xF8, + 0x00, 0x10, 0x01, 0x20, 0x6E, 0x4A, 0x81, 0xF8, 0x1B, 0x80, 0x03, 0x90, 0x06, 0x9B, 0x8D, 0xE8, + 0x0C, 0x01, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0x62, 0xFD, 0xD9, 0xF8, + 0x00, 0x00, 0xA5, 0x21, 0x81, 0x76, 0x01, 0x21, 0x06, 0xA8, 0x0D, 0xF0, 0x1E, 0xFF, 0x07, 0xB0, + 0xBD, 0xE8, 0xF0, 0x8F, 0xD9, 0xF8, 0x00, 0x10, 0x00, 0x20, 0xC8, 0x76, 0x01, 0x21, 0xB0, 0x20, + 0x05, 0xE0, 0xD9, 0xF8, 0x00, 0x10, 0x00, 0x20, 0xC8, 0x76, 0x01, 0x21, 0xB1, 0x20, 0x0F, 0xF0, + 0xBB, 0xFB, 0xE4, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x5C, 0x91, 0x8D, 0xB0, 0xD9, 0xF8, + 0x00, 0x00, 0x90, 0xF8, 0x31, 0x80, 0x90, 0xF8, 0x30, 0xA0, 0x13, 0xF0, 0x6E, 0xF9, 0x04, 0x46, + 0x0D, 0x46, 0x13, 0xF0, 0x6C, 0xF9, 0x06, 0x46, 0xD9, 0xF8, 0x00, 0x00, 0x0F, 0x46, 0x90, 0xF8, + 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0xAA, 0xFC, + 0x04, 0x46, 0x0D, 0x46, 0x01, 0x21, 0x04, 0xA8, 0x0D, 0xF0, 0x84, 0xFE, 0xDF, 0xF8, 0x1C, 0x91, + 0x00, 0x21, 0x04, 0x9B, 0xD9, 0xF8, 0x00, 0x00, 0xDF, 0xF8, 0x18, 0xB1, 0x90, 0xF9, 0x1D, 0x20, + 0xCD, 0xE9, 0x02, 0x21, 0xCD, 0xE9, 0x00, 0xB3, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, + 0x10, 0xF0, 0x0F, 0xFD, 0x01, 0x21, 0x00, 0x22, 0x04, 0x9B, 0xCD, 0xE9, 0x02, 0x21, 0xCD, 0xE9, + 0x00, 0xB3, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0x02, 0xFD, 0x34, 0x48, + 0x34, 0x30, 0x13, 0xF0, 0x93, 0xF8, 0x32, 0x49, 0x06, 0x20, 0x34, 0x31, 0x08, 0x71, 0x08, 0x46, + 0xFF, 0xF7, 0x6A, 0xFE, 0x2E, 0x48, 0x02, 0x21, 0x80, 0x68, 0x00, 0x90, 0x0C, 0xA8, 0x0D, 0xF0, + 0x51, 0xFE, 0x2D, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0xC8, 0x11, 0xB0, 0xF9, 0xCA, 0x21, 0x11, 0x44, + 0x49, 0x10, 0x03, 0x91, 0x08, 0xFB, 0x0A, 0xF1, 0x01, 0x91, 0x90, 0xF8, 0xE8, 0x00, 0x80, 0x07, + 0x0A, 0xD4, 0xAA, 0xF1, 0x01, 0x01, 0x08, 0xFB, 0x01, 0xF0, 0x00, 0x99, 0x01, 0x90, 0x53, 0x46, + 0x42, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x2C, 0xFA, 0xDD, 0xE9, 0x00, 0x02, 0x0C, 0x99, 0x11, 0xF0, + 0xCA, 0xF9, 0x82, 0x46, 0x02, 0x21, 0x0C, 0xA8, 0x0D, 0xF0, 0x8F, 0xFE, 0x1A, 0x48, 0x4F, 0xF0, + 0x00, 0x08, 0x00, 0x68, 0xB0, 0xF9, 0xC8, 0x21, 0x52, 0x45, 0x03, 0xDB, 0xB0, 0xF9, 0xCA, 0x21, + 0x52, 0x45, 0x08, 0xDD, 0x03, 0x9A, 0xB0, 0xF8, 0xCC, 0x01, 0xAA, 0xEB, 0x02, 0x01, 0x91, 0xFB, + 0xF0, 0xF0, 0x4F, 0xFA, 0x80, 0xF8, 0x04, 0x99, 0xCD, 0xE9, 0x00, 0x18, 0x32, 0x46, 0x3B, 0x46, + 0x20, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0x41, 0xFE, 0x4F, 0xF4, 0x80, 0x71, 0x01, 0x28, 0x29, 0xD0, + 0x02, 0x28, 0x2D, 0xD0, 0xD9, 0xF8, 0x00, 0x10, 0x32, 0x46, 0x81, 0xF8, 0x1D, 0x80, 0x01, 0x21, + 0x04, 0x9B, 0xCD, 0xF8, 0x00, 0xB0, 0x03, 0x91, 0xCD, 0xE9, 0x01, 0x38, 0x3B, 0x46, 0x0B, 0xE0, + 0x7C, 0x08, 0x10, 0x00, 0xE1, 0x08, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, + 0xFC, 0x4C, 0x01, 0x20, 0x24, 0x52, 0x01, 0x20, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0x89, 0xFC, + 0xD9, 0xF8, 0x00, 0x00, 0xA5, 0x21, 0x01, 0x77, 0x01, 0x21, 0x04, 0xA8, 0x0D, 0xF0, 0x45, 0xFE, + 0x0D, 0xB0, 0x25, 0xE7, 0xD9, 0xF8, 0x00, 0x20, 0x00, 0x20, 0x50, 0x77, 0xB0, 0x20, 0x04, 0xE0, + 0xD9, 0xF8, 0x00, 0x20, 0x00, 0x20, 0x50, 0x77, 0xB1, 0x20, 0x0F, 0xF0, 0xE5, 0xFA, 0xE7, 0xE7, + 0x2D, 0xE9, 0xF0, 0x4F, 0xF3, 0x48, 0x8F, 0xB0, 0x00, 0x68, 0x90, 0xF8, 0x31, 0x60, 0x90, 0xF8, + 0x30, 0x00, 0x06, 0x90, 0x13, 0xF0, 0x99, 0xF8, 0x80, 0x46, 0x89, 0x46, 0x13, 0xF0, 0x97, 0xF8, + 0x04, 0x46, 0x0D, 0x46, 0x01, 0x21, 0x08, 0xA8, 0x0D, 0xF0, 0xBC, 0xFD, 0xEA, 0x48, 0x02, 0xAB, + 0x00, 0x27, 0x00, 0x68, 0x08, 0x9A, 0x90, 0xF9, 0x20, 0x10, 0x90, 0xF9, 0x1F, 0x00, 0x83, 0xE8, + 0x83, 0x00, 0xE6, 0x48, 0xCD, 0xE9, 0x00, 0x02, 0x0E, 0x90, 0x22, 0x46, 0x2B, 0x46, 0x40, 0x46, + 0x49, 0x46, 0x10, 0xF0, 0x97, 0xFC, 0x08, 0x99, 0xCD, 0xE9, 0x01, 0x17, 0x01, 0x20, 0xCD, 0xE9, + 0x03, 0x70, 0x0E, 0x98, 0x00, 0x90, 0x22, 0x46, 0x2B, 0x46, 0x40, 0x46, 0x49, 0x46, 0x10, 0xF0, + 0x89, 0xFC, 0xDB, 0x48, 0x12, 0xF0, 0xCA, 0xFF, 0xD9, 0x49, 0x03, 0x20, 0x88, 0x71, 0x08, 0x46, + 0xFF, 0xF7, 0xA2, 0xFD, 0xD6, 0x48, 0x02, 0x21, 0x34, 0x38, 0xD0, 0xE9, 0x06, 0x70, 0x00, 0x90, + 0xD0, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0xCE, 0xA1, 0xB0, 0xF9, 0xD0, 0xB1, 0x05, 0xA8, 0x0D, 0xF0, + 0x81, 0xFD, 0x0A, 0xEB, 0x0B, 0x00, 0x40, 0x10, 0x0D, 0x90, 0xCA, 0x48, 0x00, 0x68, 0x90, 0xF8, + 0x34, 0x01, 0x80, 0x07, 0x05, 0xD4, 0x39, 0x46, 0x32, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x7C, 0xF9, + 0x76, 0x1E, 0x32, 0x46, 0x38, 0x46, 0x05, 0x99, 0x11, 0xF0, 0x05, 0xF9, 0x00, 0x27, 0x50, 0x45, + 0x01, 0xDC, 0x58, 0x45, 0x08, 0xDA, 0x0D, 0x99, 0x09, 0x1A, 0xBE, 0x48, 0x00, 0x68, 0xB0, 0xF8, + 0xD2, 0x01, 0x91, 0xFB, 0xF0, 0xF0, 0x47, 0xB2, 0xBA, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x34, 0x01, + 0x80, 0x07, 0x07, 0xD4, 0x00, 0x99, 0x06, 0x9A, 0x08, 0x46, 0x00, 0xF0, 0x5D, 0xF9, 0x06, 0x98, + 0x40, 0x1E, 0x06, 0x90, 0xDD, 0xE9, 0x05, 0x12, 0x00, 0x98, 0x11, 0xF0, 0xE4, 0xF8, 0x00, 0x26, + 0x50, 0x45, 0x01, 0xDC, 0x58, 0x45, 0x08, 0xDA, 0x0D, 0x99, 0x09, 0x1A, 0xAD, 0x48, 0x00, 0x68, + 0xB0, 0xF8, 0xD4, 0x01, 0x91, 0xFB, 0xF0, 0xF0, 0x46, 0xB2, 0x02, 0x21, 0x05, 0xA8, 0x0D, 0xF0, + 0x9C, 0xFD, 0x08, 0x98, 0xCD, 0xE9, 0x00, 0x07, 0x22, 0x46, 0x2B, 0x46, 0x02, 0x96, 0x40, 0x46, + 0x49, 0x46, 0xFF, 0xF7, 0x90, 0xFD, 0x01, 0x28, 0x1E, 0xD0, 0x02, 0x28, 0x25, 0xD0, 0xA2, 0x48, + 0x22, 0x46, 0x2B, 0x46, 0x00, 0x68, 0xC7, 0x77, 0x80, 0xF8, 0x20, 0x60, 0x01, 0x20, 0x08, 0x99, + 0xCD, 0xE9, 0x03, 0x60, 0xCD, 0xE9, 0x01, 0x17, 0x0E, 0x98, 0x00, 0x90, 0x40, 0x46, 0x49, 0x46, + 0x10, 0xF0, 0x08, 0xFC, 0x98, 0x48, 0xA5, 0x21, 0x00, 0x68, 0x81, 0x77, 0x01, 0x21, 0x08, 0xA8, + 0x0D, 0xF0, 0x73, 0xFD, 0x0F, 0xB0, 0x53, 0xE6, 0x93, 0x49, 0x00, 0x20, 0x09, 0x68, 0xC8, 0x77, + 0x81, 0xF8, 0x20, 0x00, 0x10, 0x21, 0xB2, 0x20, 0x07, 0xE0, 0x8F, 0x49, 0x00, 0x20, 0x09, 0x68, + 0xC8, 0x77, 0x81, 0xF8, 0x20, 0x00, 0x10, 0x21, 0xB3, 0x20, 0x0F, 0xF0, 0x0D, 0xFA, 0xE1, 0xE7, + 0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x12, 0xF0, 0xC8, 0xFF, 0x06, 0x46, 0x0F, 0x46, 0x12, 0xF0, + 0xC6, 0xFF, 0xDF, 0xF8, 0x10, 0xB2, 0x01, 0x21, 0xDA, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8, + 0x31, 0x50, 0x05, 0xA8, 0x0D, 0xF0, 0xE6, 0xFC, 0x7F, 0x4C, 0x02, 0xA9, 0x4F, 0xF0, 0x00, 0x08, + 0x20, 0x68, 0x05, 0x9B, 0xDF, 0xF8, 0xF4, 0x91, 0x90, 0xF9, 0x23, 0x20, 0x90, 0xF9, 0x22, 0x00, + 0x09, 0xF1, 0x98, 0x09, 0x81, 0xE8, 0x05, 0x01, 0xCD, 0xE9, 0x00, 0x93, 0x42, 0x46, 0x43, 0x46, + 0x30, 0x46, 0x39, 0x46, 0x10, 0xF0, 0xBE, 0xFB, 0x05, 0x9A, 0xCD, 0xE9, 0x01, 0x28, 0x01, 0x21, + 0xCD, 0xF8, 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x81, 0x00, 0x22, 0x13, 0x46, 0x30, 0x46, 0x39, 0x46, + 0x10, 0xF0, 0xB0, 0xFB, 0x6E, 0x48, 0x12, 0xF0, 0xF1, 0xFE, 0x6D, 0x49, 0x03, 0x20, 0x08, 0x72, + 0x08, 0x46, 0xFF, 0xF7, 0xC9, 0xFC, 0x6A, 0x48, 0x02, 0x21, 0x34, 0x38, 0xD0, 0xF8, 0x28, 0x90, + 0x06, 0xA8, 0x0D, 0xF0, 0xAF, 0xFC, 0xDA, 0xF8, 0x00, 0x00, 0xB0, 0xF9, 0xD6, 0x11, 0xB0, 0xF9, + 0xD8, 0x21, 0x90, 0xF8, 0x84, 0x09, 0x11, 0x44, 0x01, 0xEB, 0xD1, 0x71, 0x4F, 0xEA, 0x61, 0x0A, + 0x80, 0x07, 0x05, 0xD4, 0x6D, 0x1E, 0x49, 0x46, 0x2A, 0x46, 0x08, 0x46, 0x00, 0xF0, 0xA4, 0xF8, + 0x2A, 0x46, 0x48, 0x46, 0x06, 0x99, 0x11, 0xF0, 0x2E, 0xF8, 0xDB, 0xF8, 0x00, 0x10, 0x00, 0x25, + 0xA9, 0x46, 0xB1, 0xF9, 0xD6, 0x21, 0x82, 0x42, 0x03, 0xDB, 0xB1, 0xF9, 0xD8, 0x21, 0x82, 0x42, + 0x06, 0xDD, 0xB1, 0xF8, 0xDA, 0x11, 0xAA, 0xEB, 0x00, 0x00, 0x90, 0xFB, 0xF1, 0xF0, 0x45, 0xB2, + 0x02, 0x21, 0x06, 0xA8, 0x0D, 0xF0, 0xE1, 0xFC, 0x05, 0x99, 0x00, 0x22, 0x8D, 0xE8, 0x22, 0x02, + 0x13, 0x46, 0x30, 0x46, 0x39, 0x46, 0xFF, 0xF7, 0xD6, 0xFC, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, + 0x22, 0xD0, 0x21, 0x68, 0x45, 0x48, 0x01, 0xF8, 0x22, 0x5F, 0x81, 0xF8, 0x01, 0x80, 0x01, 0x21, + 0x05, 0x9A, 0xCD, 0xE9, 0x03, 0x81, 0x8D, 0xE8, 0x25, 0x00, 0x00, 0x22, 0x13, 0x46, 0x30, 0x46, + 0x39, 0x46, 0x10, 0xF0, 0x4F, 0xFB, 0x21, 0x68, 0xA5, 0x20, 0x81, 0xF8, 0x21, 0x00, 0x01, 0x21, + 0x05, 0xA8, 0x0D, 0xF0, 0xBA, 0xFC, 0x9A, 0xE5, 0x21, 0x68, 0x01, 0xF8, 0x22, 0x8F, 0x81, 0xF8, + 0x01, 0x80, 0x40, 0x21, 0xB2, 0x20, 0x06, 0xE0, 0x21, 0x68, 0xB3, 0x20, 0x01, 0xF8, 0x22, 0x8F, + 0x81, 0xF8, 0x01, 0x80, 0x40, 0x21, 0x0F, 0xF0, 0x57, 0xF9, 0xE4, 0xE7, 0x70, 0xB5, 0x04, 0x46, + 0x00, 0x20, 0x13, 0xF0, 0xC8, 0xFB, 0x02, 0x20, 0x13, 0xF0, 0xC5, 0xFB, 0x29, 0x4D, 0x28, 0x68, + 0x90, 0xF8, 0xC0, 0x01, 0x20, 0x40, 0xC0, 0x07, 0x01, 0xD0, 0xFF, 0xF7, 0xC2, 0xFC, 0x28, 0x68, + 0x90, 0xF8, 0xC0, 0x01, 0x80, 0x07, 0x03, 0xD5, 0xA0, 0x07, 0x01, 0xD5, 0xFF, 0xF7, 0x82, 0xFD, + 0x28, 0x68, 0x90, 0xF8, 0xC0, 0x01, 0x40, 0x07, 0x03, 0xD5, 0x60, 0x07, 0x01, 0xD5, 0xFF, 0xF7, + 0x4F, 0xFE, 0x28, 0x68, 0x90, 0xF8, 0xC0, 0x01, 0x00, 0x07, 0x03, 0xD5, 0x20, 0x07, 0x01, 0xD5, + 0xFF, 0xF7, 0x1E, 0xFF, 0x02, 0x20, 0x13, 0xF0, 0xB9, 0xFB, 0x00, 0x20, 0x13, 0xF0, 0xB6, 0xFB, + 0xE0, 0x07, 0x04, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0x01, 0xF0, 0xC9, 0xB9, 0x70, 0xBD, + 0xF0, 0xB5, 0x00, 0x26, 0x35, 0x46, 0x0C, 0xE0, 0x01, 0x24, 0x07, 0xE0, 0x05, 0xFB, 0x03, 0x47, + 0x64, 0x1C, 0x31, 0xF8, 0x17, 0x70, 0x20, 0xF8, 0x16, 0x70, 0x76, 0x1C, 0x9C, 0x42, 0xF5, 0xDB, + 0x6D, 0x1C, 0x95, 0x42, 0xF0, 0xDB, 0xF0, 0xBD, 0x30, 0xB5, 0x00, 0x24, 0x01, 0x23, 0x05, 0xE0, + 0x31, 0xF8, 0x13, 0x50, 0x20, 0xF8, 0x14, 0x50, 0x5B, 0x1C, 0x64, 0x1C, 0x93, 0x42, 0xF7, 0xDB, + 0x30, 0xBD, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0xEC, 0x57, 0x01, 0x20, + 0xB0, 0x08, 0x10, 0x00, 0x70, 0xB5, 0x6D, 0x4D, 0x4F, 0xF4, 0x26, 0x74, 0x21, 0x46, 0x28, 0x68, + 0x14, 0xF0, 0xCA, 0xF8, 0x00, 0x21, 0x1F, 0x20, 0x0E, 0xF1, 0x6A, 0xFD, 0x22, 0x46, 0x29, 0x68, + 0xBD, 0xE8, 0x70, 0x40, 0x1F, 0x23, 0x66, 0x48, 0x14, 0xF0, 0xE5, 0xB8, 0x63, 0x48, 0x10, 0xB5, + 0x00, 0x68, 0x64, 0x4C, 0x90, 0xF8, 0x3F, 0x10, 0x20, 0x68, 0x01, 0x76, 0x4F, 0xF4, 0x8C, 0x61, + 0x14, 0xF0, 0xB2, 0xF8, 0x00, 0x21, 0x1A, 0x20, 0x0E, 0xF1, 0x52, 0xFD, 0x00, 0x21, 0x1B, 0x20, + 0x0E, 0xF1, 0x4E, 0xFD, 0x1A, 0x23, 0x4F, 0xF4, 0x80, 0x62, 0x5B, 0x48, 0x21, 0x68, 0x14, 0xF0, + 0xCA, 0xF8, 0x21, 0x68, 0x1B, 0x23, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x22, 0x57, 0x48, 0x01, 0xF5, + 0x80, 0x51, 0x14, 0xF0, 0xC0, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x55, 0x4D, 0x04, 0x1D, 0x0E, 0x46, + 0x21, 0x46, 0x28, 0x46, 0x14, 0xF0, 0x90, 0xF8, 0x30, 0x68, 0x52, 0x49, 0x00, 0xEB, 0x84, 0x03, + 0x8B, 0x42, 0x01, 0xD2, 0x1C, 0x23, 0x12, 0xE0, 0x4F, 0x4A, 0x93, 0x42, 0x12, 0xD2, 0x88, 0x42, + 0x0C, 0xD2, 0x88, 0x46, 0x09, 0x1A, 0x8F, 0x08, 0x1C, 0x23, 0x3A, 0x46, 0x29, 0x46, 0x14, 0xF0, + 0xA2, 0xF8, 0xE2, 0x1B, 0x05, 0xEB, 0x87, 0x01, 0x1D, 0x23, 0x11, 0xE0, 0x1D, 0x23, 0x22, 0x46, + 0x29, 0x46, 0x0E, 0xE0, 0x90, 0x42, 0x14, 0xD2, 0x11, 0x1A, 0x8F, 0x08, 0x90, 0x46, 0x1D, 0x23, + 0x3A, 0x46, 0x29, 0x46, 0x14, 0xF0, 0x8F, 0xF8, 0xE2, 0x1B, 0x05, 0xEB, 0x87, 0x01, 0x1E, 0x23, + 0x40, 0x46, 0x14, 0xF0, 0x88, 0xF8, 0x30, 0x68, 0x00, 0xEB, 0x84, 0x00, 0x30, 0x60, 0xBD, 0xE8, + 0xF0, 0x81, 0x1E, 0x23, 0xE3, 0xE7, 0xF8, 0xB5, 0x35, 0x4C, 0x38, 0x48, 0x00, 0x90, 0x10, 0x34, + 0x02, 0x20, 0x13, 0xF0, 0xE8, 0xFA, 0x00, 0x21, 0x1C, 0x20, 0x0E, 0xF1, 0xF1, 0xFC, 0x00, 0x21, + 0x1D, 0x20, 0x0E, 0xF1, 0xED, 0xFC, 0x00, 0x21, 0x1E, 0x20, 0x0E, 0xF1, 0xE9, 0xFC, 0x10, 0x21, + 0x20, 0x46, 0x15, 0xF0, 0x46, 0xFB, 0x00, 0x20, 0x20, 0x80, 0xA0, 0x70, 0x23, 0x4D, 0x01, 0x20, + 0xE0, 0x70, 0x28, 0x68, 0xC1, 0x8A, 0xA1, 0x80, 0x81, 0x8A, 0xE1, 0x80, 0x28, 0x49, 0xC2, 0x8A, + 0xA1, 0xF8, 0xFA, 0x2E, 0x80, 0x8A, 0xA1, 0xF8, 0xF8, 0x0E, 0x04, 0x20, 0x69, 0x46, 0xFF, 0xF7, + 0x92, 0xFF, 0x01, 0x23, 0x00, 0x22, 0x21, 0x46, 0x10, 0x20, 0x10, 0xF0, 0x46, 0xFC, 0x06, 0x46, + 0x69, 0x46, 0xFF, 0xF7, 0x88, 0xFF, 0x01, 0x23, 0x00, 0x22, 0x21, 0x46, 0x11, 0x20, 0x10, 0xF0, + 0x3C, 0xFC, 0x69, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x7E, 0xFF, 0x29, 0x68, 0x91, 0xF8, 0x50, 0x02, + 0xC0, 0x07, 0x03, 0xD1, 0x91, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x09, 0xD0, 0x01, 0x23, 0x00, 0x22, + 0x21, 0x46, 0x12, 0x20, 0x10, 0xF0, 0x29, 0xFC, 0x69, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x6B, 0xFF, + 0x01, 0x23, 0x00, 0x22, 0x21, 0x46, 0x13, 0x20, 0x10, 0xF0, 0x1F, 0xFC, 0x69, 0x46, 0x30, 0x46, + 0xFF, 0xF7, 0x61, 0xFF, 0x02, 0x20, 0x13, 0xF0, 0xA9, 0xFA, 0xF8, 0xBD, 0x20, 0x07, 0x10, 0x00, + 0xF0, 0xEF, 0x01, 0x00, 0x24, 0x07, 0x10, 0x00, 0xF0, 0x9F, 0x01, 0x00, 0xF0, 0xAF, 0x01, 0x00, + 0x84, 0x5A, 0x10, 0x00, 0xF0, 0xCF, 0x01, 0x00, 0xF0, 0xDF, 0x01, 0x00, 0xF0, 0xBF, 0x01, 0x00, + 0xFC, 0x4C, 0x01, 0x20, 0x0B, 0x48, 0x01, 0x78, 0x5A, 0x29, 0x11, 0xD1, 0x81, 0x88, 0xB1, 0xF5, + 0x7C, 0x7F, 0x0D, 0xD8, 0x41, 0x88, 0x00, 0x29, 0x0A, 0xD1, 0x06, 0x49, 0x40, 0x78, 0x10, 0x31, + 0x02, 0x28, 0x05, 0xD0, 0xA0, 0xF1, 0x70, 0x02, 0x07, 0x2A, 0x01, 0xD8, 0x0F, 0xF0, 0xBF, 0xB9, + 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFE, 0x48, + 0x15, 0xF0, 0x8D, 0xFA, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x13, 0xF0, 0xB3, 0xB9, + 0x2D, 0xE9, 0xF0, 0x41, 0xF9, 0x4C, 0xA0, 0xF1, 0x60, 0x06, 0x09, 0x2E, 0xD4, 0xE9, 0x12, 0x05, + 0xD4, 0xE9, 0x14, 0x23, 0x16, 0xD2, 0xDF, 0xE8, 0x06, 0xF0, 0x05, 0x16, 0x26, 0x37, 0x46, 0x58, + 0x67, 0x78, 0x87, 0x00, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x9D, 0xF9, 0x02, 0x46, + 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xEF, 0xF9, 0xD4, 0xE9, 0x02, 0x23, 0x10, 0x43, 0x19, 0x43, + 0xC4, 0xE9, 0x02, 0x01, 0x75, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x8E, 0xF9, 0x01, 0x23, 0x02, 0x46, + 0x00, 0x21, 0x18, 0x46, 0x15, 0xF0, 0xDF, 0xF9, 0xD4, 0xE9, 0x0A, 0x23, 0x10, 0x43, 0x19, 0x43, + 0xC4, 0xE9, 0x0A, 0x01, 0x65, 0xE0, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x7C, 0xF9, + 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xCE, 0xF9, 0xD4, 0xE9, 0x06, 0x23, 0x10, 0x43, + 0x19, 0x43, 0xC4, 0xE9, 0x06, 0x01, 0x54, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x6D, 0xF9, 0x02, 0x46, + 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xBF, 0xF9, 0xD4, 0xE9, 0x0E, 0x23, 0x10, 0x43, 0x19, 0x43, + 0xC4, 0xE9, 0x0E, 0x01, 0x45, 0xE0, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x5C, 0xF9, + 0x01, 0x23, 0x02, 0x46, 0x00, 0x21, 0x18, 0x46, 0x15, 0xF0, 0xAD, 0xF9, 0xD4, 0xE9, 0x04, 0x23, + 0x10, 0x43, 0x19, 0x43, 0xC4, 0xE9, 0x04, 0x01, 0x33, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x4C, 0xF9, + 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0x9E, 0xF9, 0xD4, 0xE9, 0x0C, 0x23, 0x10, 0x43, + 0x19, 0x43, 0xC4, 0xE9, 0x0C, 0x01, 0x24, 0xE0, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, + 0x3B, 0xF9, 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0x8D, 0xF9, 0xD4, 0xE9, 0x08, 0x23, + 0x10, 0x43, 0x19, 0x43, 0xC4, 0xE9, 0x08, 0x01, 0x13, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x2C, 0xF9, + 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0x7E, 0xF9, 0xD4, 0xE9, 0x10, 0x23, 0x10, 0x43, + 0x19, 0x43, 0xC4, 0xE9, 0x10, 0x01, 0x04, 0xE0, 0x01, 0x20, 0x88, 0x40, 0x61, 0x68, 0x08, 0x43, + 0x60, 0x60, 0x20, 0x68, 0x40, 0x1C, 0x20, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x41, + 0x17, 0x46, 0x04, 0x46, 0x0D, 0x46, 0x00, 0x26, 0x09, 0xE0, 0xE0, 0x07, 0x03, 0xD0, 0x31, 0x46, + 0x38, 0x46, 0x0E, 0xF0, 0x31, 0xFF, 0x76, 0x1C, 0x6D, 0x08, 0x4F, 0xEA, 0x34, 0x04, 0x54, 0xEA, + 0x05, 0x00, 0xF2, 0xD1, 0xE8, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0xA0, 0x4C, 0xD4, 0xE9, 0x02, 0x23, + 0xD4, 0xE9, 0x06, 0x56, 0x10, 0x46, 0x19, 0x46, 0x2A, 0x43, 0x33, 0x43, 0xD4, 0xE9, 0x0A, 0x56, + 0xD4, 0xE9, 0x0E, 0xC7, 0x45, 0xEA, 0x0C, 0x05, 0x3E, 0x43, 0xD4, 0xE9, 0x08, 0x7C, 0x97, 0x43, + 0x2C, 0xEA, 0x03, 0x0C, 0xC4, 0xE9, 0x08, 0x7C, 0xD4, 0xE9, 0x10, 0x23, 0xAA, 0x43, 0xB3, 0x43, + 0xC4, 0xE9, 0x10, 0x23, 0x22, 0x68, 0x00, 0x2A, 0xC6, 0xD0, 0x60, 0x22, 0xFF, 0xF7, 0xC6, 0xFF, + 0xD4, 0xE9, 0x0A, 0x01, 0x61, 0x22, 0xFF, 0xF7, 0xC1, 0xFF, 0xD4, 0xE9, 0x06, 0x01, 0x62, 0x22, + 0xFF, 0xF7, 0xBC, 0xFF, 0xD4, 0xE9, 0x0E, 0x01, 0x63, 0x22, 0xFF, 0xF7, 0xB7, 0xFF, 0xD4, 0xE9, + 0x04, 0x01, 0x64, 0x22, 0xFF, 0xF7, 0xB2, 0xFF, 0xD4, 0xE9, 0x0C, 0x01, 0x65, 0x22, 0xFF, 0xF7, + 0xAD, 0xFF, 0xD4, 0xE9, 0x08, 0x01, 0x66, 0x22, 0xFF, 0xF7, 0xA8, 0xFF, 0xD4, 0xE9, 0x10, 0x01, + 0x67, 0x22, 0xFF, 0xF7, 0xA3, 0xFF, 0x60, 0x68, 0xBD, 0xE8, 0xF0, 0x41, 0x68, 0x22, 0x00, 0x21, + 0x9C, 0xE7, 0x99, 0xE7, 0x2D, 0xE9, 0xF1, 0x4F, 0x4F, 0xF0, 0x00, 0x09, 0x12, 0xF0, 0x95, 0xFC, + 0x06, 0x46, 0x88, 0x46, 0x12, 0xF0, 0x93, 0xFC, 0x74, 0x4A, 0x04, 0x46, 0x0D, 0x46, 0xC2, 0xE9, + 0x14, 0x01, 0xC2, 0xE9, 0x12, 0x68, 0x4F, 0xF0, 0x1D, 0x0A, 0x4F, 0xF0, 0x26, 0x0B, 0x13, 0xF0, + 0x8C, 0xFB, 0x00, 0x27, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xEC, 0xF8, 0x30, 0x40, + 0x01, 0xEA, 0x08, 0x01, 0x08, 0x43, 0x22, 0xD0, 0xF8, 0xB2, 0x00, 0x21, 0x13, 0xF0, 0x85, 0xFB, + 0x41, 0x07, 0x05, 0xD5, 0x00, 0x99, 0xC9, 0x06, 0x02, 0xD5, 0x49, 0x46, 0x62, 0x20, 0x10, 0xE0, + 0xC1, 0x07, 0x05, 0xD0, 0x00, 0x99, 0x49, 0x07, 0x02, 0xD5, 0x49, 0x46, 0x60, 0x20, 0x08, 0xE0, + 0x00, 0x99, 0x11, 0xF0, 0xC0, 0x0F, 0x06, 0xD0, 0x10, 0xF0, 0x0A, 0x0F, 0x03, 0xD0, 0x49, 0x46, + 0x64, 0x20, 0xFF, 0xF7, 0xBD, 0xFE, 0x09, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x09, 0x7F, 0x1C, + 0x57, 0x45, 0xCF, 0xDB, 0x13, 0xF0, 0x59, 0xFB, 0x00, 0x27, 0x3E, 0x46, 0x32, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x15, 0xF0, 0xB8, 0xF8, 0x20, 0x40, 0x29, 0x40, 0x08, 0x43, 0x20, 0xD0, 0xF0, 0xB2, + 0x01, 0x21, 0x13, 0xF0, 0x52, 0xFB, 0x41, 0x07, 0x05, 0xD5, 0x00, 0x99, 0x89, 0x06, 0x02, 0xD5, + 0x39, 0x46, 0x63, 0x20, 0x10, 0xE0, 0xC1, 0x07, 0x05, 0xD0, 0x00, 0x99, 0x09, 0x07, 0x02, 0xD5, + 0x39, 0x46, 0x61, 0x20, 0x08, 0xE0, 0x00, 0x99, 0x11, 0xF4, 0xC0, 0x7F, 0x06, 0xD0, 0x10, 0xF0, + 0x0A, 0x0F, 0x03, 0xD0, 0x39, 0x46, 0x65, 0x20, 0xFF, 0xF7, 0x8A, 0xFE, 0x7F, 0x1C, 0xFF, 0xB2, + 0x76, 0x1C, 0x5E, 0x45, 0xD2, 0xDD, 0xBD, 0xE8, 0xF8, 0x4F, 0x13, 0xF0, 0x26, 0xBB, 0x10, 0xB5, + 0x04, 0x46, 0x00, 0x20, 0x13, 0xF0, 0xCF, 0xF8, 0x38, 0x49, 0x00, 0x20, 0x14, 0xF0, 0x0C, 0x0F, + 0xC1, 0xE9, 0x08, 0x00, 0xC1, 0xE9, 0x02, 0x00, 0xC1, 0xE9, 0x04, 0x00, 0xC1, 0xE9, 0x06, 0x00, + 0xC1, 0xE9, 0x10, 0x00, 0xC1, 0xE9, 0x0A, 0x00, 0xC1, 0xE9, 0x0C, 0x00, 0xC1, 0xE9, 0x0E, 0x00, + 0x48, 0x60, 0x08, 0x60, 0x09, 0xD1, 0xE0, 0x06, 0x07, 0xD4, 0xA0, 0x06, 0x05, 0xD4, 0x60, 0x06, + 0x03, 0xD4, 0xE0, 0x05, 0x01, 0xD4, 0x20, 0x06, 0x02, 0xD5, 0x20, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, + 0xA0, 0x07, 0x02, 0xD0, 0x20, 0x46, 0x00, 0xF0, 0x22, 0xF8, 0xFF, 0xF7, 0x04, 0xFF, 0xBD, 0xE8, + 0x10, 0x40, 0x00, 0x20, 0x13, 0xF0, 0xBA, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x16, 0x46, 0x1F, 0x46, + 0x80, 0x46, 0x4F, 0xF0, 0xFF, 0x35, 0x00, 0x24, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, + 0x4A, 0xF8, 0x30, 0x40, 0x39, 0x40, 0x08, 0x43, 0x04, 0xD0, 0x6D, 0x1C, 0x45, 0x45, 0x01, 0xD1, + 0x20, 0x46, 0xD1, 0xE6, 0x64, 0x1C, 0x40, 0x2C, 0xEE, 0xD3, 0x00, 0x20, 0xCC, 0xE6, 0x2D, 0xE9, + 0xFF, 0x41, 0x04, 0x46, 0x01, 0x20, 0x00, 0xF0, 0x31, 0xF8, 0x80, 0x46, 0x12, 0xF0, 0xC5, 0xFB, + 0xCD, 0xE9, 0x00, 0x01, 0x12, 0xF0, 0xC3, 0xFB, 0xCD, 0xE9, 0x02, 0x01, 0x08, 0x21, 0x68, 0x46, + 0x13, 0xF0, 0xA0, 0xFD, 0x07, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x13, 0xF0, 0x9B, 0xFD, 0x05, 0x46, + 0x07, 0x4E, 0xE0, 0x07, 0x07, 0xD0, 0x30, 0x68, 0x42, 0x46, 0x29, 0x46, 0xB0, 0xF8, 0xDE, 0x30, + 0x38, 0x46, 0x00, 0xF0, 0x4C, 0xF8, 0x05, 0xE0, 0xC0, 0x08, 0x10, 0x00, 0x08, 0x04, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xA0, 0x07, 0x07, 0xD5, 0x30, 0x68, 0x42, 0x46, 0x29, 0x46, 0xB0, 0xF8, + 0xDE, 0x30, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF8, 0xBD, 0xE8, 0xFF, 0x81, 0x30, 0xB5, 0x85, 0xB0, + 0x04, 0x46, 0x68, 0x46, 0x12, 0xF0, 0xF2, 0xFA, 0x67, 0x48, 0x00, 0x90, 0x67, 0x48, 0x00, 0x68, + 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x02, 0xD0, 0x01, 0x20, 0x8D, 0xF8, 0x0B, 0x00, 0x02, 0x2C, + 0x15, 0xD0, 0x07, 0x20, 0x8D, 0xF8, 0x04, 0x00, 0x61, 0x4C, 0x68, 0x46, 0x12, 0xF0, 0x03, 0xFB, + 0x00, 0x22, 0x04, 0xAB, 0x01, 0x21, 0x10, 0x46, 0x12, 0xF0, 0xD6, 0xFF, 0x01, 0x21, 0x00, 0x20, + 0x12, 0xF0, 0xB5, 0xFF, 0x20, 0x78, 0x30, 0xB1, 0x0E, 0xF0, 0xBD, 0xFD, 0xED, 0xE7, 0x03, 0x20, + 0x8D, 0xF8, 0x09, 0x00, 0xE8, 0xE7, 0x12, 0xF0, 0x68, 0xFB, 0x56, 0x4D, 0xC5, 0xE9, 0x12, 0x01, + 0x12, 0xF0, 0x65, 0xFB, 0xC5, 0xE9, 0x14, 0x01, 0xA0, 0x68, 0x05, 0xB0, 0x30, 0xBD, 0x2D, 0xE9, + 0xFF, 0x5F, 0x9B, 0x46, 0x92, 0x46, 0x0F, 0x46, 0x00, 0x25, 0x44, 0xE0, 0x00, 0x98, 0x4F, 0xF0, + 0x00, 0x09, 0x4C, 0x46, 0xA0, 0xF1, 0x01, 0x08, 0x3A, 0xE0, 0x00, 0xBF, 0x04, 0xFB, 0x07, 0x50, + 0x81, 0xB2, 0x60, 0x1C, 0x00, 0xFB, 0x07, 0x50, 0x80, 0xB2, 0x3A, 0xF8, 0x11, 0x20, 0x3A, 0xF8, + 0x10, 0x00, 0x10, 0x1A, 0x00, 0xB2, 0x58, 0x45, 0x02, 0xDD, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, + 0xCB, 0xF1, 0x00, 0x01, 0x88, 0x42, 0x13, 0xDA, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xD0, 0x4F, 0xF0, + 0x00, 0x09, 0x21, 0x46, 0x18, 0xE0, 0x4F, 0xF0, 0x01, 0x09, 0x14, 0xE0, 0x00, 0x26, 0x04, 0xE0, + 0x31, 0x46, 0x66, 0x20, 0xFF, 0xF7, 0x8C, 0xFD, 0x76, 0x1C, 0xA6, 0x42, 0xF8, 0xD9, 0x0E, 0xE0, + 0xB9, 0xF1, 0x00, 0x0F, 0x0B, 0xD0, 0x21, 0x46, 0x66, 0x20, 0xFF, 0xF7, 0x81, 0xFD, 0x00, 0x98, + 0x80, 0x1E, 0x84, 0x42, 0x03, 0xD1, 0x61, 0x1C, 0x66, 0x20, 0xFF, 0xF7, 0x79, 0xFD, 0x64, 0x1C, + 0x44, 0x45, 0xC3, 0xD3, 0x6D, 0x1C, 0xBD, 0x42, 0xB8, 0xD3, 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, + 0xFF, 0x5F, 0x9B, 0x46, 0x92, 0x46, 0x0D, 0x46, 0x00, 0x26, 0x41, 0xE0, 0x4F, 0xF0, 0x00, 0x09, + 0x4C, 0x46, 0xA5, 0xF1, 0x01, 0x08, 0x38, 0xE0, 0x06, 0xFB, 0x05, 0x40, 0x61, 0x1C, 0x06, 0xFB, + 0x05, 0x11, 0x80, 0xB2, 0x89, 0xB2, 0x3A, 0xF8, 0x10, 0x20, 0x3A, 0xF8, 0x11, 0x00, 0x10, 0x1A, + 0x00, 0xB2, 0x58, 0x45, 0x02, 0xDD, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0xCB, 0xF1, 0x00, 0x01, + 0x88, 0x42, 0x13, 0xDA, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xD0, 0x4F, 0xF0, 0x00, 0x09, 0x21, 0x46, + 0x17, 0xE0, 0x4F, 0xF0, 0x01, 0x09, 0x13, 0xE0, 0x00, 0x27, 0x04, 0xE0, 0x39, 0x46, 0x67, 0x20, + 0xFF, 0xF7, 0x3E, 0xFD, 0x7F, 0x1C, 0xA7, 0x42, 0xF8, 0xD9, 0x0D, 0xE0, 0xB9, 0xF1, 0x00, 0x0F, + 0x0A, 0xD0, 0x21, 0x46, 0x67, 0x20, 0xFF, 0xF7, 0x33, 0xFD, 0xA8, 0x1E, 0x84, 0x42, 0x03, 0xD1, + 0x61, 0x1C, 0x67, 0x20, 0xFF, 0xF7, 0x2C, 0xFD, 0x64, 0x1C, 0x44, 0x45, 0xC4, 0xD3, 0x76, 0x1C, + 0x00, 0x98, 0x86, 0x42, 0xBA, 0xD3, 0xB0, 0xE7, 0x29, 0x13, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xC0, 0x08, 0x10, 0x00, 0x08, 0x04, 0x10, 0x00, 0x11, 0x49, 0x08, 0x60, 0x4F, 0xF4, 0x00, 0x51, + 0x00, 0x20, 0x12, 0xF0, 0xC8, 0xBE, 0x38, 0xB5, 0xAF, 0xF2, 0x13, 0x00, 0x14, 0xF0, 0xC2, 0xFD, + 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x54, 0x6B, 0x46, 0x21, 0x46, 0x10, 0x46, 0x12, 0xF0, 0x04, 0xFF, + 0x21, 0x46, 0x00, 0x20, 0x12, 0xF0, 0xE3, 0xFE, 0x06, 0x48, 0xA5, 0x22, 0x01, 0x68, 0x04, 0x48, + 0x0A, 0x74, 0x00, 0x68, 0x20, 0xF0, 0x7F, 0x42, 0x4A, 0x61, 0x14, 0xF0, 0xC9, 0xFD, 0x38, 0xBD, + 0x60, 0x04, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0x02, 0x00, 0x04, 0xD0, 0x01, 0x2A, 0x04, 0xD0, + 0x02, 0x28, 0x03, 0xD1, 0x04, 0xE0, 0x01, 0x20, 0x00, 0xE0, 0x04, 0x20, 0x12, 0xF0, 0x8F, 0xB9, + 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFE, 0x48, 0x14, 0xF0, 0x67, 0xFF, + 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x12, 0xF0, 0x8D, 0xBE, 0x30, 0xB5, 0x85, 0xB0, + 0x04, 0x46, 0x68, 0x46, 0x12, 0xF0, 0xD2, 0xF9, 0xF7, 0x48, 0x00, 0x90, 0x02, 0x20, 0x6C, 0xB3, + 0x01, 0x2C, 0x2D, 0xD0, 0x02, 0x2C, 0x2D, 0xD0, 0x03, 0x2C, 0x25, 0xD1, 0x5F, 0xF0, 0x08, 0x01, + 0x8D, 0xF8, 0x04, 0x10, 0xF1, 0x49, 0x09, 0x68, 0x91, 0xF8, 0xB0, 0x10, 0xCA, 0x07, 0x04, 0xD0, + 0x89, 0x07, 0x00, 0xD4, 0x01, 0x20, 0x8D, 0xF8, 0x0B, 0x00, 0xEA, 0x4D, 0x03, 0x24, 0x68, 0x46, + 0x12, 0xF0, 0xD9, 0xF9, 0x00, 0x22, 0x04, 0xAB, 0x01, 0x21, 0x10, 0x46, 0x12, 0xF0, 0xAC, 0xFE, + 0x01, 0x21, 0x00, 0x20, 0x12, 0xF0, 0x8B, 0xFE, 0x28, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x0E, 0xF0, + 0x92, 0xFC, 0x64, 0x1E, 0x00, 0x2C, 0xEA, 0xDC, 0x05, 0xB0, 0x30, 0xBD, 0x05, 0x21, 0xD7, 0xE7, + 0x06, 0x21, 0xD5, 0xE7, 0x8D, 0xF8, 0x09, 0x00, 0xD4, 0xE7, 0x2D, 0xE9, 0xF1, 0x4F, 0x88, 0xB0, + 0x12, 0xF0, 0x33, 0xFA, 0x83, 0x46, 0x02, 0x91, 0x12, 0xF0, 0x31, 0xFA, 0x81, 0x46, 0xD7, 0x4C, + 0x08, 0x98, 0x8A, 0x46, 0x00, 0x28, 0x20, 0x68, 0x07, 0xD0, 0xB0, 0xF8, 0x7A, 0x11, 0x08, 0x98, + 0xFF, 0xF7, 0x92, 0xFF, 0x04, 0x90, 0xD2, 0x48, 0x12, 0xE0, 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, + 0x60, 0x0F, 0x05, 0xD0, 0x58, 0x46, 0x02, 0x99, 0x0F, 0xF0, 0x64, 0xFD, 0x83, 0x46, 0x02, 0x91, + 0x20, 0x68, 0xB0, 0xF8, 0x72, 0x11, 0x08, 0x98, 0xFF, 0xF7, 0x7E, 0xFF, 0x04, 0x90, 0xC9, 0x48, + 0x03, 0x90, 0x40, 0x20, 0x07, 0x90, 0x06, 0x90, 0xC2, 0x48, 0xB8, 0x21, 0xB8, 0x38, 0x14, 0xF0, + 0x4A, 0xFF, 0x00, 0x20, 0x00, 0x90, 0x08, 0x98, 0xFF, 0xF7, 0x88, 0xFF, 0xBD, 0x48, 0x00, 0x27, + 0x3E, 0x46, 0x80, 0x68, 0x05, 0x90, 0x01, 0x20, 0x3D, 0x46, 0x01, 0x90, 0x2A, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x14, 0xF0, 0x60, 0xFE, 0x02, 0x9A, 0x00, 0xEA, 0x0B, 0x00, 0x11, 0x40, 0x08, 0x43, + 0x41, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x54, 0xFE, 0x02, 0x46, + 0x0B, 0x46, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0A, 0x01, 0x08, 0x43, 0x20, 0xD0, 0xAD, 0x48, + 0xB8, 0x38, 0x00, 0xEB, 0xC6, 0x01, 0x8E, 0x46, 0x03, 0xC9, 0x00, 0xEA, 0x02, 0x0C, 0x01, 0xEA, + 0x03, 0x08, 0x5C, 0xEA, 0x08, 0x0C, 0x12, 0xD1, 0xDD, 0xF8, 0x14, 0xC0, 0x3C, 0xF9, 0x17, 0x80, + 0xDD, 0xF8, 0x10, 0xC0, 0xE0, 0x45, 0x04, 0xDC, 0x10, 0x43, 0x19, 0x43, 0xCE, 0xE9, 0x00, 0x01, + 0x05, 0xE0, 0x22, 0x46, 0x31, 0x46, 0x00, 0x9B, 0x03, 0x98, 0x13, 0xF0, 0x1E, 0xF8, 0x7F, 0x1C, + 0x06, 0x98, 0x64, 0x1C, 0x84, 0x42, 0xCD, 0xDB, 0x9A, 0x48, 0xB8, 0x38, 0x00, 0xEB, 0xC6, 0x01, + 0xD1, 0xE9, 0x00, 0x02, 0x80, 0xEA, 0x09, 0x00, 0x82, 0xEA, 0x0A, 0x02, 0x10, 0x43, 0x01, 0xD0, + 0x00, 0x20, 0x01, 0x90, 0x76, 0x1C, 0x07, 0x98, 0x6D, 0x1C, 0x85, 0x42, 0xAE, 0xDB, 0x01, 0x98, + 0x01, 0x28, 0x04, 0xD0, 0x00, 0x98, 0x40, 0x1C, 0x00, 0x90, 0x7F, 0x28, 0x9B, 0xDD, 0x01, 0x98, + 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xF1, 0x4F, 0x98, 0xB0, 0x12, 0xF0, 0x95, 0xF9, + 0xCD, 0xE9, 0x0C, 0x01, 0x12, 0xF0, 0x93, 0xF9, 0xCD, 0xE9, 0x10, 0x01, 0x18, 0x98, 0x87, 0x4C, + 0x00, 0x28, 0x5C, 0xD0, 0x20, 0x68, 0xB0, 0xF8, 0x7A, 0x11, 0x18, 0x98, 0xFF, 0xF7, 0xF4, 0xFE, + 0x0F, 0x90, 0x83, 0x48, 0x06, 0x90, 0x40, 0x20, 0x82, 0x46, 0x0E, 0x90, 0x08, 0x21, 0x0C, 0xA8, + 0x13, 0xF0, 0x60, 0xFB, 0x04, 0x46, 0x08, 0x21, 0x10, 0xA8, 0x13, 0xF0, 0x5B, 0xFB, 0x44, 0x43, + 0x7D, 0x48, 0x01, 0x90, 0x00, 0xF5, 0xE6, 0x60, 0x21, 0x46, 0x02, 0x90, 0x14, 0xF0, 0x91, 0xFE, + 0x61, 0x00, 0x01, 0x98, 0x14, 0xF0, 0x8D, 0xFE, 0x72, 0x48, 0xB8, 0x21, 0xB8, 0x38, 0x14, 0xF0, + 0xAA, 0xFE, 0x4F, 0xF0, 0x00, 0x09, 0x18, 0x98, 0xFF, 0xF7, 0xE8, 0xFE, 0x6D, 0x48, 0x00, 0x27, + 0x3C, 0x46, 0x80, 0x68, 0x0A, 0x90, 0xC9, 0xF1, 0x00, 0x00, 0x4F, 0xF0, 0x01, 0x0B, 0x3E, 0x46, + 0x13, 0x90, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0xBD, 0xFD, 0xDD, 0xE9, 0x0C, 0x23, + 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x6E, 0xD0, 0x00, 0x25, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x14, 0xF0, 0xB1, 0xFD, 0xDD, 0xE9, 0x10, 0x8C, 0x02, 0x46, 0x0B, 0x46, 0x00, 0xEA, 0x08, 0x00, + 0x01, 0xEA, 0x0C, 0x01, 0x08, 0x43, 0x73, 0xD0, 0x5A, 0x48, 0xB8, 0x38, 0x00, 0xEB, 0xC7, 0x0C, + 0xDC, 0xE9, 0x00, 0x01, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x0F, 0xD0, 0x93, 0xE0, 0xDD, 0xE9, + 0x0C, 0x01, 0x0F, 0xF0, 0x77, 0xFC, 0xCD, 0xE9, 0x0C, 0x01, 0x20, 0x68, 0xB0, 0xF8, 0x72, 0x11, + 0x18, 0x98, 0xFF, 0xF7, 0x91, 0xFE, 0x0F, 0x90, 0x52, 0x48, 0x9B, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, + 0x0A, 0xDA, 0x0A, 0x98, 0x30, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x81, 0x42, 0x01, 0xDB, 0x00, 0x21, + 0x00, 0xE0, 0x01, 0x21, 0x02, 0x98, 0x01, 0x55, 0x0A, 0x98, 0x0F, 0x99, 0x30, 0xF9, 0x14, 0x00, + 0x88, 0x42, 0x31, 0xDD, 0x02, 0x99, 0x09, 0x5D, 0x11, 0xB1, 0x01, 0x29, 0x09, 0xD0, 0x6A, 0xE0, + 0xB9, 0xF1, 0x7F, 0x0F, 0x67, 0xDA, 0x01, 0x99, 0x09, 0xF1, 0x01, 0x03, 0x21, 0xF8, 0x14, 0x00, + 0x51, 0xE0, 0xDC, 0xE9, 0x00, 0x10, 0x11, 0x43, 0x18, 0x43, 0xCC, 0xE9, 0x00, 0x10, 0x01, 0x98, + 0x30, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x09, 0x1A, 0x0A, 0x98, 0x30, 0xF9, 0x14, 0x20, 0x0F, 0x98, + 0xA2, 0xEB, 0x00, 0x00, 0x00, 0xD5, 0x49, 0x42, 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x81, 0x42, + 0x05, 0xDC, 0x13, 0x9B, 0x2A, 0x46, 0x39, 0x46, 0x5B, 0x1C, 0x06, 0x98, 0x36, 0xE0, 0x01, 0x98, + 0x20, 0xF8, 0x14, 0x20, 0x3F, 0xE0, 0x52, 0xE0, 0x37, 0xDA, 0x02, 0x99, 0x09, 0x5D, 0x01, 0x29, + 0x01, 0xD0, 0x71, 0xB1, 0x37, 0xE0, 0x13, 0x99, 0x11, 0xF1, 0x7F, 0x0F, 0x33, 0xDD, 0x01, 0x99, + 0x2A, 0x46, 0x21, 0xF8, 0x14, 0x00, 0x13, 0x9B, 0x39, 0x46, 0x5B, 0x1E, 0x06, 0x98, 0x1D, 0xE0, + 0x2A, 0xE0, 0xDC, 0xE9, 0x00, 0x10, 0x11, 0x43, 0x18, 0x43, 0xCC, 0xE9, 0x00, 0x10, 0x01, 0x98, + 0x0F, 0x9A, 0x30, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x08, 0x1A, 0x0A, 0x99, 0x31, 0xF9, 0x14, 0x10, + 0xA1, 0xEB, 0x02, 0x02, 0x00, 0xD5, 0x40, 0x42, 0x00, 0x2A, 0x00, 0xDA, 0x52, 0x42, 0x90, 0x42, + 0x07, 0xDC, 0xA9, 0xF1, 0x01, 0x03, 0x2A, 0x46, 0x39, 0x46, 0x06, 0x98, 0x12, 0xF0, 0x05, 0xFF, + 0x09, 0xE0, 0x01, 0x98, 0x20, 0xF8, 0x14, 0x10, 0x05, 0xE0, 0xDC, 0xE9, 0x00, 0x10, 0x11, 0x43, + 0x18, 0x43, 0xCC, 0xE9, 0x00, 0x10, 0x64, 0x1C, 0x6D, 0x1C, 0x55, 0x45, 0xFF, 0xF6, 0x4D, 0xAF, + 0x08, 0x48, 0xB8, 0x38, 0x00, 0xEB, 0xC7, 0x01, 0xD1, 0xE9, 0x00, 0x01, 0xDD, 0xE9, 0x10, 0x23, + 0x50, 0x40, 0x59, 0x40, 0x08, 0x43, 0x01, 0xD0, 0x4F, 0xF0, 0x00, 0x0B, 0x7F, 0x1C, 0x76, 0x1C, + 0x0E, 0x98, 0x0B, 0xE0, 0xB0, 0x09, 0x10, 0x00, 0x75, 0x19, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x24, 0x52, 0x01, 0x20, 0xFC, 0x4C, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0x86, 0x42, 0xFF, 0xF6, + 0x20, 0xAF, 0xBB, 0xF1, 0x01, 0x0F, 0x05, 0xD0, 0x09, 0xF1, 0x01, 0x09, 0xB9, 0xF1, 0x7F, 0x0F, + 0x7F, 0xF7, 0x09, 0xAF, 0x58, 0x46, 0x19, 0xB0, 0xCB, 0xE6, 0x2D, 0xE9, 0xF1, 0x4F, 0x98, 0xB0, + 0x4F, 0xF0, 0x00, 0x0A, 0x12, 0xF0, 0x61, 0xF8, 0xCD, 0xE9, 0x0E, 0x01, 0x12, 0xF0, 0x5F, 0xF8, + 0xCD, 0xE9, 0x10, 0x01, 0x18, 0x98, 0x48, 0xB1, 0xFD, 0x48, 0x00, 0x68, 0xB0, 0xF8, 0x7A, 0x11, + 0x18, 0x98, 0xFF, 0xF7, 0xC1, 0xFD, 0x13, 0x90, 0xFA, 0x48, 0x14, 0xE0, 0xF8, 0x4C, 0x20, 0x68, + 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0xDD, 0xE9, 0x0E, 0x01, 0x0F, 0xF0, + 0x91, 0xFB, 0xCD, 0xE9, 0x0E, 0x01, 0x20, 0x68, 0xB0, 0xF8, 0x72, 0x11, 0x18, 0x98, 0xFF, 0xF7, + 0xAB, 0xFD, 0x13, 0x90, 0xF0, 0x48, 0x40, 0x25, 0xCD, 0xE9, 0x04, 0x05, 0x08, 0x21, 0x0E, 0xA8, + 0x13, 0xF0, 0x18, 0xFA, 0x03, 0x90, 0x08, 0x21, 0x10, 0xA8, 0x13, 0xF0, 0x13, 0xFA, 0x0A, 0x90, + 0xB8, 0x21, 0xEA, 0x48, 0x14, 0xF0, 0x6F, 0xFD, 0x01, 0x20, 0x12, 0x90, 0x00, 0x20, 0x04, 0x46, + 0x08, 0x90, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x8D, 0xFC, 0xDD, 0xE9, 0x10, 0x23, + 0x81, 0x46, 0x8B, 0x46, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x7D, 0xD0, 0xDC, 0x48, 0x00, 0x68, + 0x90, 0xF8, 0x70, 0x01, 0x80, 0x07, 0x13, 0xD5, 0x08, 0x98, 0x80, 0xB1, 0x00, 0x26, 0x0B, 0xE0, + 0x31, 0x46, 0x02, 0x9A, 0x04, 0x98, 0x12, 0xF0, 0x5D, 0xFE, 0x03, 0x46, 0x22, 0x46, 0x31, 0x46, + 0x04, 0x98, 0x12, 0xF0, 0x62, 0xFE, 0x76, 0x1C, 0x03, 0x98, 0x86, 0x42, 0xF0, 0xDB, 0x02, 0x94, + 0x18, 0x98, 0xFF, 0xF7, 0x83, 0xFD, 0xD1, 0x48, 0x4F, 0xF0, 0x01, 0x08, 0xB8, 0x30, 0x00, 0x27, + 0x80, 0x68, 0x3E, 0x46, 0x16, 0x90, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x5B, 0xFC, + 0xDD, 0xE9, 0x0E, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x45, 0xD0, 0xC7, 0x48, 0x00, 0xEB, + 0xC7, 0x01, 0x0D, 0x91, 0xD1, 0xE9, 0x00, 0x01, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0B, 0x01, + 0x08, 0x43, 0x2E, 0xD1, 0x22, 0x46, 0x39, 0x46, 0x04, 0x98, 0x12, 0xF0, 0x2B, 0xFE, 0x0A, 0x9A, + 0x08, 0x99, 0x07, 0xFB, 0x02, 0x12, 0x16, 0x99, 0x31, 0xF9, 0x12, 0x20, 0x13, 0x99, 0x8A, 0x42, + 0x0A, 0xDA, 0x0D, 0x98, 0x0D, 0x99, 0xD0, 0xE9, 0x00, 0x30, 0x43, 0xEA, 0x09, 0x03, 0x40, 0xEA, + 0x0B, 0x00, 0xC1, 0xE9, 0x00, 0x30, 0x14, 0xE0, 0x7F, 0x28, 0x06, 0xDA, 0x43, 0x1C, 0x22, 0x46, + 0x39, 0x46, 0x04, 0x98, 0x12, 0xF0, 0x19, 0xFE, 0x0B, 0xE0, 0x0D, 0x98, 0x0D, 0x9A, 0xD0, 0xE9, + 0x00, 0x10, 0x41, 0xEA, 0x09, 0x01, 0x40, 0xEA, 0x0B, 0x00, 0xC2, 0xE9, 0x00, 0x10, 0x00, 0x20, + 0x12, 0x90, 0x0D, 0x99, 0xD1, 0xE9, 0x00, 0x01, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0B, 0x01, + 0x08, 0x43, 0x00, 0xD1, 0x80, 0x46, 0x7F, 0x1C, 0x76, 0x1C, 0xAE, 0x42, 0xAB, 0xDB, 0xB8, 0xF1, + 0x00, 0x0F, 0x9D, 0xD0, 0x08, 0x98, 0x00, 0xE0, 0x01, 0xE0, 0x40, 0x1C, 0x08, 0x90, 0x05, 0x98, + 0x64, 0x1C, 0x84, 0x42, 0xFF, 0xF6, 0x6D, 0xAF, 0x00, 0x20, 0xB9, 0xE0, 0x4F, 0xF0, 0x00, 0x08, + 0x46, 0x46, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0xF5, 0xFB, 0xDD, 0xE9, 0x10, 0x23, + 0x83, 0x46, 0x03, 0x91, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x76, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, + 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0x18, 0x98, 0xFF, 0xF7, 0x00, 0xFD, 0x8F, 0x48, 0x4F, 0xF0, + 0x01, 0x09, 0xB8, 0x30, 0x00, 0x24, 0x80, 0x68, 0x27, 0x46, 0x16, 0x90, 0x3A, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x14, 0xF0, 0xD8, 0xFB, 0xDD, 0xE9, 0x0E, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, + 0x78, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0x0E, 0xDD, 0x32, 0x46, 0x21, 0x46, 0x04, 0x98, 0x12, 0xF0, + 0xB1, 0xFD, 0x82, 0x49, 0x32, 0x46, 0xEC, 0x31, 0x09, 0x57, 0x0B, 0x18, 0x21, 0x46, 0x04, 0x98, + 0x12, 0xF0, 0xB3, 0xFD, 0x65, 0xE0, 0xBA, 0xF1, 0x01, 0x0F, 0x12, 0xD1, 0x32, 0x46, 0x21, 0x46, + 0x04, 0x98, 0x12, 0xF0, 0x9F, 0xFD, 0x79, 0x49, 0xEC, 0x31, 0x08, 0x55, 0x77, 0x48, 0x00, 0xEB, + 0xC4, 0x02, 0xD2, 0xE9, 0x00, 0x01, 0x03, 0x9B, 0x20, 0xEA, 0x0B, 0x00, 0x99, 0x43, 0xC2, 0xE9, + 0x00, 0x01, 0x72, 0x48, 0x00, 0xEB, 0xC4, 0x01, 0x0B, 0x91, 0xD1, 0xE9, 0x00, 0x01, 0x03, 0x9A, + 0x00, 0xEA, 0x0B, 0x00, 0x11, 0x40, 0x08, 0x43, 0x39, 0xD1, 0x32, 0x46, 0x21, 0x46, 0x04, 0x98, + 0x12, 0xF0, 0x80, 0xFD, 0x0A, 0x9A, 0x16, 0x99, 0x04, 0xFB, 0x02, 0x82, 0x31, 0xF9, 0x12, 0x20, + 0x13, 0x99, 0x8A, 0x42, 0x10, 0xDA, 0x0B, 0x9A, 0xDD, 0xF8, 0x0C, 0xC0, 0xD2, 0xE9, 0x00, 0x13, + 0x41, 0xEA, 0x0B, 0x01, 0x43, 0xEA, 0x0C, 0x03, 0xC2, 0xE9, 0x00, 0x13, 0x5F, 0x49, 0xEC, 0x31, + 0x0A, 0x5D, 0x80, 0x1A, 0x08, 0x55, 0x1A, 0xE0, 0x7F, 0x28, 0x07, 0xDA, 0x43, 0x1C, 0x32, 0x46, + 0x21, 0x46, 0x04, 0x98, 0x12, 0xF0, 0x69, 0xFD, 0x11, 0xE0, 0x27, 0xE0, 0x0B, 0x99, 0xD1, 0xE9, + 0x00, 0x32, 0x03, 0x99, 0x43, 0xEA, 0x0B, 0x03, 0x0A, 0x43, 0x0B, 0x99, 0xC1, 0xE9, 0x00, 0x32, + 0x52, 0x49, 0xEC, 0x31, 0x0A, 0x5D, 0x80, 0x1A, 0x08, 0x55, 0x00, 0x20, 0x12, 0x90, 0x0B, 0x98, + 0x03, 0x9A, 0xD0, 0xE9, 0x00, 0x10, 0x01, 0xEA, 0x0B, 0x01, 0x10, 0x40, 0x01, 0x43, 0x00, 0xD1, + 0x89, 0x46, 0x64, 0x1C, 0x7F, 0x1C, 0xAF, 0x42, 0xFF, 0xF6, 0x78, 0xAF, 0x4F, 0xF0, 0x00, 0x0A, + 0xB9, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x67, 0xAF, 0x08, 0xF1, 0x01, 0x08, 0x05, 0x98, 0x76, 0x1C, + 0x86, 0x42, 0xFF, 0xF6, 0x4E, 0xAF, 0x18, 0x98, 0xFF, 0xF7, 0x60, 0xFC, 0x0C, 0x98, 0x40, 0x1C, + 0x0C, 0x90, 0x3B, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x70, 0x11, 0x0C, 0x98, 0xB0, 0xEB, 0x11, 0x1F, + 0xFF, 0xF6, 0x3C, 0xAF, 0x12, 0x98, 0x5E, 0xE6, 0x2D, 0xE9, 0xF0, 0x4F, 0x04, 0x46, 0x85, 0xB0, + 0x00, 0x20, 0x12, 0xF0, 0x78, 0xFB, 0x02, 0x20, 0x12, 0xF0, 0x75, 0xFB, 0x11, 0xF0, 0xBF, 0xFE, + 0xCD, 0xE9, 0x02, 0x01, 0x32, 0x48, 0x04, 0x90, 0x40, 0x27, 0x08, 0x21, 0x02, 0xA8, 0x13, 0xF0, + 0x99, 0xF8, 0x80, 0x46, 0x01, 0x2C, 0x7F, 0xD1, 0xDD, 0xE9, 0x02, 0x01, 0xCD, 0xE9, 0x00, 0x01, + 0x01, 0x22, 0x00, 0x23, 0x04, 0x98, 0x12, 0xF0, 0x17, 0xFD, 0xDF, 0xF8, 0xA8, 0x90, 0x00, 0x20, + 0x6F, 0xF0, 0x7E, 0x05, 0x09, 0xEB, 0x48, 0x0B, 0x69, 0x0C, 0x04, 0xE0, 0x29, 0xF8, 0x10, 0x10, + 0x0B, 0xF8, 0x00, 0x50, 0x40, 0x1C, 0x40, 0x45, 0xF8, 0xDB, 0x03, 0x20, 0xFF, 0xF7, 0x1E, 0xFC, + 0x1E, 0x48, 0xB8, 0x30, 0x00, 0x24, 0xD0, 0xF8, 0x08, 0xA0, 0x26, 0x46, 0x32, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x14, 0xF0, 0xF8, 0xFA, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, + 0x1D, 0xD0, 0x3A, 0xF9, 0x14, 0x10, 0x39, 0xF9, 0x14, 0x00, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, + 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x81, 0x42, 0x0A, 0xDA, 0x32, 0x46, 0x00, 0x21, 0x04, 0x98, + 0x12, 0xF0, 0xC8, 0xFC, 0x0B, 0xF8, 0x04, 0x00, 0x3A, 0xF8, 0x14, 0x10, 0x29, 0xF8, 0x14, 0x10, + 0x2B, 0x46, 0x32, 0x46, 0x00, 0x21, 0x04, 0x98, 0x12, 0xF0, 0xC7, 0xFC, 0x64, 0x1C, 0x76, 0x1C, + 0xBE, 0x42, 0xD3, 0xDB, 0x6D, 0x1C, 0x7F, 0x2D, 0xC7, 0xDD, 0x00, 0x25, 0x2C, 0x46, 0x0B, 0xE0, + 0x20, 0x07, 0x10, 0x00, 0x24, 0x52, 0x01, 0x20, 0xFC, 0x4C, 0x01, 0x20, 0xF8, 0x08, 0x10, 0x00, + 0xF8, 0x5B, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, + 0xBA, 0xFA, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x07, 0xD0, 0x1B, 0xF9, + 0x05, 0x30, 0x22, 0x46, 0x00, 0x21, 0x04, 0x98, 0x12, 0xF0, 0x9F, 0xFC, 0x6D, 0x1C, 0x64, 0x1C, + 0xBC, 0x42, 0xDC, 0xDB, 0x76, 0x48, 0x26, 0x22, 0x04, 0x99, 0x00, 0x68, 0x00, 0xF5, 0x86, 0x50, + 0x00, 0xE0, 0x01, 0xE0, 0x14, 0xF0, 0xD6, 0xFA, 0x00, 0x26, 0x72, 0x4D, 0x34, 0x46, 0x22, 0x46, + 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x97, 0xFA, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, + 0x08, 0x43, 0x07, 0xD0, 0x22, 0x46, 0x00, 0x21, 0x04, 0x98, 0x12, 0xF0, 0x73, 0xFC, 0x25, 0xF8, + 0x16, 0x00, 0x76, 0x1C, 0x64, 0x1C, 0xBC, 0x42, 0xE9, 0xDB, 0x03, 0x20, 0xFF, 0xF7, 0x9E, 0xFB, + 0x65, 0x48, 0x81, 0x68, 0x00, 0x20, 0x06, 0xE0, 0x31, 0xF8, 0x10, 0x30, 0x08, 0xEB, 0x00, 0x02, + 0x40, 0x1C, 0x25, 0xF8, 0x12, 0x30, 0x40, 0x45, 0xF6, 0xDB, 0x02, 0x20, 0x12, 0xF0, 0xD6, 0xFA, + 0x00, 0x20, 0x12, 0xF0, 0xD3, 0xFA, 0x05, 0xB0, 0x63, 0xE4, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, + 0x01, 0x24, 0x00, 0x20, 0x12, 0xF0, 0xAF, 0xFA, 0x02, 0x20, 0x12, 0xF0, 0xAC, 0xFA, 0x54, 0x4E, + 0xE8, 0x07, 0x4F, 0xF0, 0x00, 0x07, 0x4F, 0xF0, 0xA5, 0x08, 0x08, 0xD0, 0x00, 0xF0, 0x20, 0xF8, + 0x10, 0xF0, 0x01, 0x04, 0x03, 0xD0, 0x30, 0x68, 0xC7, 0x76, 0x80, 0xF8, 0x1A, 0x80, 0xA8, 0x07, + 0x08, 0xD5, 0x00, 0xF0, 0x63, 0xF8, 0x20, 0x40, 0x04, 0x00, 0x03, 0xD0, 0x30, 0x68, 0x47, 0x77, + 0x80, 0xF8, 0x1C, 0x80, 0x00, 0x20, 0x12, 0xF0, 0xA9, 0xFA, 0x02, 0x20, 0x12, 0xF0, 0xA6, 0xFA, + 0xE8, 0x07, 0x02, 0xD0, 0x01, 0x20, 0x00, 0xF0, 0xBB, 0xF8, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, + 0x2D, 0xE9, 0xFC, 0x47, 0x01, 0x26, 0x11, 0xF0, 0xC8, 0xFD, 0x04, 0x46, 0x0D, 0x46, 0x11, 0xF0, + 0xC6, 0xFD, 0xDF, 0xF8, 0xF8, 0x90, 0x07, 0x46, 0x88, 0x46, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, + 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0x20, 0x46, 0x29, 0x46, 0x0F, 0xF0, 0x02, 0xF9, + 0x04, 0x46, 0x0D, 0x46, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x70, 0x01, 0xC0, 0x07, 0x27, 0xD0, + 0xCD, 0xE9, 0x00, 0x78, 0x22, 0x46, 0x2B, 0x46, 0x31, 0x48, 0x12, 0xF0, 0x15, 0xFC, 0xD9, 0xF8, + 0x00, 0x00, 0x90, 0xF8, 0x70, 0x11, 0xC9, 0x07, 0x1A, 0xD0, 0x90, 0xF8, 0xE8, 0x10, 0x89, 0x07, + 0x03, 0xD4, 0x00, 0x20, 0xFF, 0xF7, 0x31, 0xFD, 0x0C, 0xE0, 0x90, 0xF8, 0xE7, 0x00, 0xC0, 0xF3, + 0x41, 0x10, 0x02, 0x28, 0x4F, 0xF0, 0x00, 0x00, 0x02, 0xD3, 0xFF, 0xF7, 0xF4, 0xFB, 0x01, 0xE0, + 0xFF, 0xF7, 0x53, 0xFB, 0x06, 0x00, 0x03, 0xD1, 0x01, 0x21, 0x74, 0x20, 0x0D, 0xF0, 0xC4, 0xFF, + 0x00, 0x20, 0xFF, 0xF7, 0x0B, 0xFB, 0x30, 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x2D, 0xE9, 0xFC, 0x41, + 0x01, 0x24, 0x11, 0xF0, 0x7A, 0xFD, 0x05, 0x46, 0x0E, 0x46, 0x11, 0xF0, 0x78, 0xFD, 0x17, 0x4F, + 0x3A, 0x68, 0x92, 0xF8, 0x78, 0x21, 0xD2, 0x07, 0x1C, 0xD0, 0xCD, 0xE9, 0x00, 0x01, 0x2A, 0x46, + 0x33, 0x46, 0x14, 0x48, 0x12, 0xF0, 0xD8, 0xFB, 0x38, 0x68, 0x90, 0xF8, 0x78, 0x11, 0xC9, 0x07, + 0x10, 0xD0, 0x90, 0xF8, 0xE8, 0x00, 0x80, 0x07, 0x20, 0x46, 0x02, 0xD4, 0xFF, 0xF7, 0xF5, 0xFC, + 0x01, 0xE0, 0xFF, 0xF7, 0x22, 0xFB, 0x04, 0x00, 0x04, 0xD1, 0x4F, 0xF4, 0x80, 0x71, 0x74, 0x20, + 0x0D, 0xF0, 0x92, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0xD9, 0xFA, 0x20, 0x46, 0xBD, 0xE8, 0xFC, 0x81, + 0x24, 0x07, 0x10, 0x00, 0xE0, 0x4A, 0x01, 0x20, 0xB0, 0x09, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xFC, 0x4C, 0x01, 0x20, 0x24, 0x52, 0x01, 0x20, 0x10, 0xB5, 0xFF, 0xF7, 0x8C, 0xFA, 0x01, 0x20, + 0xFF, 0xF7, 0x72, 0xFE, 0x01, 0x20, 0x00, 0xF0, 0xA4, 0xF9, 0x53, 0x20, 0xFF, 0xF7, 0x35, 0xFF, + 0x00, 0x28, 0x0B, 0xD0, 0x4F, 0xF4, 0xD6, 0x70, 0x00, 0xF0, 0xF7, 0xFF, 0x00, 0x28, 0x05, 0xD0, + 0xFE, 0xF7, 0xF1, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0x88, 0xBE, 0x10, 0xBD, 0x10, 0xB5, + 0xFF, 0xF7, 0x71, 0xFA, 0x01, 0x20, 0xFF, 0xF7, 0x57, 0xFE, 0x01, 0x20, 0x00, 0xF0, 0x89, 0xF9, + 0x40, 0xF2, 0xFF, 0x10, 0xFE, 0xF7, 0x02, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0x76, 0xBE, + 0x2D, 0xE9, 0xF0, 0x41, 0x12, 0x49, 0x09, 0x68, 0x91, 0xF8, 0xC1, 0x21, 0xD2, 0x07, 0x1D, 0xD0, + 0x01, 0x28, 0x1B, 0xD1, 0x10, 0x4F, 0x91, 0xF8, 0x31, 0x20, 0x91, 0xF8, 0x30, 0x10, 0x3D, 0x68, + 0x4A, 0x43, 0x02, 0x20, 0x0B, 0x4E, 0x14, 0xB2, 0x32, 0x35, 0xFE, 0xF7, 0x53, 0xF9, 0x03, 0x20, + 0x12, 0xF0, 0xB1, 0xF9, 0x38, 0x68, 0x62, 0x00, 0x31, 0x46, 0x04, 0x86, 0x28, 0x46, 0x14, 0xF0, + 0x99, 0xF9, 0xBD, 0xE8, 0xF0, 0x41, 0x03, 0x20, 0x12, 0xF0, 0xC0, 0xB9, 0xBD, 0xE8, 0xF0, 0x81, + 0x20, 0x07, 0x10, 0x00, 0x2E, 0x44, 0x01, 0x20, 0x24, 0x07, 0x10, 0x00, 0x10, 0xB5, 0x01, 0x46, + 0x34, 0x22, 0xFE, 0x48, 0x14, 0xF0, 0xCB, 0xF9, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, + 0x12, 0xF0, 0xF1, 0xB8, 0x30, 0xB5, 0x85, 0xB0, 0x01, 0x24, 0x68, 0x46, 0x11, 0xF0, 0x36, 0xFC, + 0xF7, 0x4B, 0x02, 0x22, 0x03, 0x21, 0x18, 0x78, 0xE0, 0xB1, 0x01, 0x28, 0x0D, 0xD0, 0x03, 0x28, + 0x0E, 0xD0, 0x02, 0x28, 0x19, 0xD0, 0x04, 0x22, 0x05, 0x28, 0x0C, 0xD0, 0x04, 0x28, 0x0D, 0xD0, + 0x06, 0x28, 0x0F, 0xD0, 0x07, 0x28, 0x10, 0xD0, 0x11, 0xE0, 0x8D, 0xF8, 0x06, 0x10, 0x0E, 0xE0, + 0x8D, 0xF8, 0x08, 0x10, 0x0B, 0xE0, 0x8D, 0xF8, 0x0A, 0x20, 0x01, 0xE0, 0x8D, 0xF8, 0x0A, 0x10, + 0x00, 0x24, 0x04, 0xE0, 0x8D, 0xF8, 0x06, 0x20, 0x01, 0xE0, 0x8D, 0xF8, 0x08, 0x20, 0xE5, 0x48, + 0x00, 0x90, 0xE5, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x21, 0xD0, 0x04, 0xB3, + 0xD8, 0x79, 0x10, 0xB1, 0x8D, 0xF8, 0x0B, 0x10, 0x02, 0xE0, 0x01, 0x20, 0x8D, 0xF8, 0x0B, 0x00, + 0xDA, 0x4D, 0x03, 0x24, 0x68, 0x46, 0x11, 0xF0, 0x1E, 0xFC, 0x00, 0x22, 0x04, 0xAB, 0x01, 0x21, + 0x10, 0x46, 0x12, 0xF0, 0xF1, 0xF8, 0x01, 0x21, 0x00, 0x20, 0x12, 0xF0, 0xD0, 0xF8, 0x28, 0x78, + 0x00, 0x28, 0x04, 0xD0, 0x0D, 0xF0, 0xD7, 0xFE, 0x64, 0x1E, 0x00, 0x2C, 0xEA, 0xDC, 0x05, 0xB0, + 0x30, 0xBD, 0x00, 0x20, 0xE2, 0xE7, 0x2D, 0xE9, 0xF3, 0x4F, 0xCD, 0x4D, 0x87, 0xB0, 0x06, 0x20, + 0x0E, 0x46, 0x28, 0x70, 0x11, 0xF0, 0x79, 0xFC, 0xCD, 0xE9, 0x04, 0x01, 0x36, 0x20, 0x02, 0x90, + 0xCA, 0x4C, 0x07, 0x98, 0x4F, 0xF0, 0x40, 0x0A, 0xC0, 0xB1, 0x01, 0x28, 0x21, 0xD0, 0x02, 0x28, + 0x7E, 0xD1, 0x07, 0x20, 0x28, 0x70, 0xC6, 0x48, 0xDF, 0xF8, 0x00, 0x83, 0x00, 0x90, 0x20, 0x68, + 0x08, 0xF1, 0x28, 0x08, 0x41, 0xF2, 0x42, 0x11, 0x08, 0x44, 0x01, 0x90, 0x08, 0x21, 0x04, 0xA8, + 0x12, 0xF0, 0x40, 0xFE, 0x04, 0x46, 0x01, 0x2E, 0x1E, 0xD0, 0x8A, 0xE0, 0xBC, 0x48, 0xDF, 0xF8, + 0xDC, 0x82, 0x48, 0x38, 0x00, 0x90, 0x08, 0xF1, 0x18, 0x08, 0x41, 0xF2, 0xE6, 0x01, 0x20, 0x68, + 0xEA, 0xE7, 0x11, 0xF0, 0x4C, 0xFC, 0xCD, 0xE9, 0x04, 0x01, 0xB5, 0x48, 0x41, 0xF2, 0x1C, 0x11, + 0x28, 0x38, 0x00, 0x90, 0x20, 0x68, 0xDF, 0xF8, 0xB4, 0x82, 0x08, 0x44, 0x01, 0x90, 0x26, 0x20, + 0x08, 0xF1, 0x1C, 0x08, 0x02, 0x90, 0xD9, 0xE7, 0x02, 0x46, 0x04, 0xA9, 0x00, 0x98, 0x12, 0xF0, + 0xE3, 0xFA, 0xDF, 0xF8, 0xB0, 0x92, 0x6F, 0xF0, 0x7E, 0x06, 0x09, 0xEB, 0x44, 0x00, 0x03, 0x90, + 0x00, 0x20, 0x71, 0x0C, 0x05, 0xE0, 0x00, 0xBF, 0x29, 0xF8, 0x10, 0x10, 0x03, 0x9A, 0x16, 0x54, + 0x40, 0x1C, 0xA0, 0x42, 0xF8, 0xDB, 0x00, 0xBF, 0xFF, 0xF7, 0x44, 0xFF, 0x00, 0x25, 0xD8, 0xF8, + 0x00, 0xB0, 0x2F, 0x46, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x84, 0xF8, 0xDD, 0xE9, + 0x04, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x1B, 0xD0, 0x3B, 0xF9, 0x15, 0x10, 0x39, 0xF9, + 0x15, 0x00, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x81, 0x42, + 0x09, 0xDA, 0x39, 0x46, 0x00, 0x98, 0x12, 0xF0, 0x9D, 0xFA, 0x03, 0x99, 0x48, 0x55, 0x3B, 0xF8, + 0x15, 0x10, 0x29, 0xF8, 0x15, 0x10, 0x32, 0x46, 0x39, 0x46, 0x00, 0x98, 0x12, 0xF0, 0x99, 0xFA, + 0x6D, 0x1C, 0xA5, 0x42, 0x02, 0xD0, 0x7F, 0x1C, 0x57, 0x45, 0xD3, 0xDB, 0x76, 0x1C, 0x00, 0xE0, + 0x54, 0xE0, 0x7F, 0x2E, 0xC8, 0xDD, 0x00, 0x26, 0x35, 0x46, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x14, 0xF0, 0x51, 0xF8, 0xDD, 0xE9, 0x04, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x06, 0xD0, + 0x03, 0x98, 0x29, 0x46, 0x82, 0x57, 0x00, 0x98, 0x12, 0xF0, 0x7B, 0xFA, 0x76, 0x1C, 0xA6, 0x42, + 0x02, 0xD0, 0x6D, 0x1C, 0x55, 0x45, 0xE8, 0xDB, 0xDD, 0xE9, 0x00, 0x10, 0x02, 0x9A, 0x14, 0xF0, + 0x71, 0xF8, 0x07, 0x98, 0x30, 0xB1, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x06, 0xD0, 0x03, 0x28, + 0x05, 0xD1, 0x03, 0xE0, 0x74, 0x4E, 0x02, 0xE0, 0x74, 0x4E, 0x00, 0xE0, 0x74, 0x4E, 0x00, 0x27, + 0x3D, 0x46, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x25, 0xF8, 0xDD, 0xE9, 0x04, 0x23, + 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x06, 0xD0, 0x29, 0x46, 0x00, 0x98, 0x12, 0xF0, 0x4A, 0xFA, + 0x26, 0xF8, 0x17, 0x00, 0x7F, 0x1C, 0xA7, 0x42, 0x02, 0xD0, 0x6D, 0x1C, 0x55, 0x45, 0xE8, 0xDB, + 0xFF, 0xF7, 0xC8, 0xFE, 0x00, 0x20, 0xD8, 0xF8, 0x00, 0x10, 0x05, 0xE0, 0x31, 0xF8, 0x10, 0x20, + 0x23, 0x18, 0x40, 0x1C, 0x26, 0xF8, 0x13, 0x20, 0xA0, 0x42, 0xF7, 0xDB, 0x09, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x12, 0xF0, 0x45, 0xF8, 0x02, 0x20, 0x12, 0xF0, + 0x42, 0xF8, 0x21, 0x46, 0x00, 0x20, 0xFF, 0xF7, 0x06, 0xFF, 0x21, 0x46, 0x01, 0x20, 0xFF, 0xF7, + 0x02, 0xFF, 0x21, 0x46, 0x02, 0x20, 0xFF, 0xF7, 0xFE, 0xFE, 0x02, 0x20, 0x12, 0xF0, 0x4E, 0xF8, + 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x12, 0xF0, 0x49, 0xB8, 0x2D, 0xE9, 0xF0, 0x47, 0x48, 0x48, + 0x00, 0x25, 0x2C, 0x46, 0xD0, 0xE9, 0x14, 0x78, 0xD0, 0xF8, 0x38, 0x90, 0x2E, 0x46, 0x82, 0x46, + 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x13, 0xF0, 0xD6, 0xFF, 0x38, 0x40, 0x01, 0xEA, 0x08, 0x01, + 0x08, 0x43, 0x04, 0xD0, 0x19, 0xF8, 0x06, 0x00, 0xA8, 0x42, 0x00, 0xD9, 0x05, 0x46, 0x76, 0x1C, + 0x40, 0x2E, 0xED, 0xD3, 0xDA, 0xE9, 0x16, 0x78, 0xDA, 0xF8, 0x3C, 0x90, 0x00, 0x26, 0x32, 0x46, + 0x01, 0x20, 0x00, 0x21, 0x13, 0xF0, 0xBF, 0xFF, 0x38, 0x40, 0x01, 0xEA, 0x08, 0x01, 0x08, 0x43, + 0x04, 0xD0, 0x19, 0xF8, 0x06, 0x00, 0xA0, 0x42, 0x00, 0xD9, 0x04, 0x46, 0x76, 0x1C, 0x40, 0x2E, + 0xED, 0xD3, 0xDA, 0xF8, 0x48, 0x20, 0x50, 0x46, 0x15, 0x70, 0xDA, 0xF8, 0x4C, 0x10, 0x0C, 0x70, + 0xDA, 0xF8, 0x30, 0x30, 0xDA, 0xF8, 0x28, 0x70, 0xDA, 0xF8, 0x34, 0x60, 0x1B, 0x78, 0x3F, 0x78, + 0x2B, 0x44, 0x3B, 0x44, 0xDA, 0xF8, 0x2C, 0x70, 0x36, 0x78, 0x3F, 0x78, 0x26, 0x44, 0x3E, 0x44, + 0xD0, 0xE9, 0x14, 0x7C, 0x57, 0xEA, 0x0C, 0x07, 0x0D, 0xD0, 0xD0, 0xE9, 0x16, 0x7C, 0x57, 0xEA, + 0x0C, 0x07, 0x0A, 0xD0, 0xFF, 0x27, 0xB3, 0x42, 0x13, 0xD2, 0xF3, 0x1A, 0x2B, 0x44, 0xFF, 0x2B, + 0x07, 0xD8, 0x13, 0x70, 0x0B, 0xE0, 0x14, 0x70, 0x09, 0xE0, 0x15, 0x70, 0x0D, 0x70, 0xBD, 0xE8, + 0xF0, 0x87, 0x17, 0x70, 0xC2, 0x69, 0x42, 0xF4, 0x00, 0x72, 0xCA, 0xF8, 0x1C, 0x20, 0x0C, 0x70, + 0xF5, 0xE7, 0x9E, 0x42, 0x0D, 0xD2, 0x9B, 0x1B, 0x23, 0x44, 0xFF, 0x2B, 0x01, 0xD8, 0x0B, 0x70, + 0x05, 0xE0, 0x0F, 0x70, 0xC1, 0x69, 0x41, 0xF4, 0x00, 0x71, 0xCA, 0xF8, 0x1C, 0x10, 0x15, 0x70, + 0xE5, 0xE7, 0x15, 0x70, 0xEB, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x1F, 0x46, 0x0D, 0x46, 0x00, 0x2A, + 0x34, 0xDD, 0x07, 0x4C, 0x1F, 0xB3, 0xB4, 0xF9, 0x0C, 0x60, 0x11, 0x46, 0x0F, 0xF0, 0x01, 0xFC, + 0xB0, 0x42, 0x28, 0x78, 0x27, 0xDA, 0xFF, 0x28, 0x1C, 0xD2, 0x13, 0xE0, 0xFC, 0x09, 0x10, 0x00, + 0x68, 0x04, 0x10, 0x00, 0xAD, 0x24, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, + 0x68, 0x5C, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0x78, 0x4B, 0x01, 0x20, 0xCC, 0x4B, 0x01, 0x20, + 0x64, 0x4C, 0x01, 0x20, 0x40, 0x1C, 0x28, 0x70, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0xB4, 0xF9, + 0x0A, 0x60, 0xDA, 0xE7, 0xE0, 0x69, 0x1F, 0xB1, 0x40, 0xF0, 0x02, 0x00, 0xE0, 0x61, 0x05, 0xE0, + 0x40, 0xF4, 0x00, 0x60, 0xFA, 0xE7, 0x08, 0xB1, 0x40, 0x1E, 0x28, 0x70, 0x01, 0x20, 0xEC, 0xE7, + 0x2D, 0xE9, 0xF0, 0x41, 0x1E, 0x46, 0x0D, 0x46, 0x00, 0x2A, 0x1A, 0xDD, 0xFE, 0x4C, 0x66, 0xB1, + 0xB4, 0xF9, 0x0C, 0x70, 0x11, 0x46, 0x0F, 0xF0, 0xC4, 0xFB, 0xB8, 0x42, 0x11, 0xDD, 0x28, 0x78, + 0x50, 0xB1, 0x10, 0x28, 0x04, 0xD3, 0x10, 0x38, 0x03, 0xE0, 0xB4, 0xF9, 0x0A, 0x70, 0xF1, 0xE7, + 0x00, 0x20, 0x28, 0x70, 0x00, 0x20, 0xD0, 0xE7, 0xE0, 0x69, 0x26, 0xB1, 0x40, 0xF0, 0x01, 0x00, + 0xE0, 0x61, 0x01, 0x20, 0xC9, 0xE7, 0x40, 0xF4, 0x80, 0x60, 0xF9, 0xE7, 0x2D, 0xE9, 0xF1, 0x4F, + 0x82, 0xB0, 0x00, 0x25, 0xEC, 0x48, 0x02, 0x9A, 0x2C, 0x46, 0xFF, 0x21, 0x02, 0xB3, 0xD0, 0xF8, + 0x30, 0x90, 0x02, 0x26, 0x4F, 0xF0, 0x18, 0x0B, 0x89, 0xF8, 0x00, 0x10, 0xD0, 0xF8, 0x34, 0x80, + 0x88, 0xF8, 0x00, 0x10, 0xB0, 0xF9, 0x0C, 0x70, 0x31, 0x02, 0x00, 0x91, 0x41, 0x69, 0x00, 0x29, + 0x00, 0xDC, 0x01, 0x25, 0xE0, 0x48, 0x80, 0x69, 0x00, 0x28, 0x00, 0xDC, 0x01, 0x24, 0xFF, 0xF7, + 0xFC, 0xFE, 0xFF, 0xF7, 0x97, 0xFD, 0x00, 0x98, 0x0D, 0xF0, 0x49, 0xFC, 0x85, 0xB1, 0x21, 0xE0, + 0xD0, 0xF8, 0x28, 0x90, 0x4F, 0xF4, 0x00, 0x66, 0x4F, 0xF0, 0x18, 0x0B, 0x89, 0xF8, 0x00, 0x10, + 0xD0, 0xF8, 0x2C, 0x80, 0x88, 0xF8, 0x00, 0x10, 0xB0, 0xF9, 0x0A, 0x70, 0xF1, 0x10, 0xDC, 0xE7, + 0xDF, 0xF8, 0x44, 0xA3, 0x3A, 0x46, 0xDA, 0xF8, 0x20, 0x00, 0xDA, 0xF8, 0x14, 0x10, 0x00, 0x68, + 0x00, 0xF0, 0x54, 0xFD, 0x01, 0x28, 0x05, 0xD1, 0xDA, 0xF8, 0x1C, 0x10, 0x31, 0x43, 0x01, 0x25, + 0xCA, 0xF8, 0x1C, 0x10, 0x8C, 0xB9, 0xDF, 0xF8, 0x20, 0xA3, 0x3A, 0x46, 0xDA, 0xF8, 0x24, 0x00, + 0xDA, 0xF8, 0x18, 0x10, 0x00, 0x68, 0x00, 0xF0, 0x41, 0xFD, 0x01, 0x28, 0x05, 0xD1, 0xDA, 0xF8, + 0x1C, 0x10, 0x31, 0x43, 0x01, 0x24, 0xCA, 0xF8, 0x1C, 0x10, 0x0D, 0xB1, 0x00, 0x2C, 0x4E, 0xD1, + 0x2F, 0x46, 0x26, 0x46, 0x4F, 0xF0, 0x17, 0x0A, 0x4F, 0xB9, 0xBB, 0x48, 0x02, 0x9B, 0x01, 0x6A, + 0x42, 0x69, 0x0F, 0x68, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x6A, 0xFF, 0x07, 0x46, 0x4E, 0xB9, + 0xB5, 0x48, 0x02, 0x9B, 0x41, 0x6A, 0x82, 0x69, 0x0E, 0x68, 0x41, 0x46, 0x30, 0x46, 0xFF, 0xF7, + 0x5F, 0xFF, 0x06, 0x46, 0xFF, 0xF7, 0xA1, 0xFE, 0xFF, 0xF7, 0x3C, 0xFD, 0x00, 0x98, 0x0D, 0xF0, + 0xEE, 0xFB, 0x07, 0xB1, 0x16, 0xB9, 0xBA, 0xF1, 0x01, 0x0A, 0xDD, 0xD2, 0x2F, 0x46, 0xAA, 0x4D, + 0xAB, 0xF1, 0x01, 0x06, 0x3F, 0xB9, 0x28, 0x6A, 0x02, 0x9B, 0x49, 0x46, 0x00, 0x68, 0x6A, 0x69, + 0xFF, 0xF7, 0x09, 0xFF, 0x07, 0x46, 0x3C, 0xB9, 0x68, 0x6A, 0x02, 0x9B, 0x41, 0x46, 0x00, 0x68, + 0xAA, 0x69, 0xFF, 0xF7, 0x00, 0xFF, 0x04, 0x46, 0xFF, 0xF7, 0x7F, 0xFE, 0xFF, 0xF7, 0x1A, 0xFD, + 0x00, 0x98, 0x0D, 0xF0, 0xCC, 0xFB, 0x07, 0xB1, 0x0C, 0xB9, 0x76, 0x1E, 0xE2, 0xD2, 0x01, 0x2F, + 0x05, 0xD1, 0x01, 0x2C, 0x03, 0xD1, 0xE8, 0x69, 0x20, 0xF4, 0x00, 0x70, 0xE8, 0x61, 0xBD, 0xE8, + 0xFE, 0x8F, 0x2D, 0xE9, 0xF0, 0x4F, 0x9A, 0x46, 0x91, 0x46, 0x00, 0x22, 0x92, 0x4B, 0x83, 0x46, + 0x14, 0x46, 0xB3, 0xF9, 0x0E, 0x70, 0x10, 0x46, 0x01, 0x23, 0x90, 0x46, 0x15, 0xE0, 0x00, 0xBF, + 0x09, 0xEB, 0xE4, 0x05, 0x04, 0xF0, 0x07, 0x0C, 0x2E, 0x78, 0x03, 0xFA, 0x0C, 0xF5, 0x35, 0x42, + 0x0A, 0xD0, 0x3B, 0xF9, 0x12, 0x50, 0xBD, 0x42, 0x03, 0xDC, 0x0A, 0xF8, 0x02, 0x30, 0x01, 0x20, + 0x01, 0xE0, 0x0A, 0xF8, 0x02, 0x80, 0x52, 0x1C, 0x64, 0x1C, 0x8A, 0x42, 0xE8, 0xDB, 0x26, 0xE6, + 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0x9A, 0x46, 0x17, 0x46, 0x25, 0x46, + 0xDF, 0xF8, 0xF4, 0x91, 0x46, 0x46, 0xDD, 0xF8, 0x3C, 0xB0, 0x4E, 0xE0, 0x0A, 0xEB, 0xE5, 0x00, + 0x05, 0xF0, 0x07, 0x01, 0x00, 0x78, 0x06, 0xFA, 0x01, 0xF2, 0x02, 0x42, 0x44, 0xD0, 0x1B, 0xF8, + 0x04, 0x00, 0x01, 0x28, 0x3F, 0xD0, 0x00, 0x98, 0xB9, 0xF9, 0x0E, 0x10, 0x30, 0xF9, 0x14, 0x20, + 0x8A, 0x42, 0x1D, 0xDA, 0x29, 0x46, 0x01, 0x98, 0x12, 0xF0, 0x61, 0xF8, 0xFF, 0x28, 0x0E, 0xDA, + 0x40, 0x1C, 0xC2, 0xB2, 0x4F, 0xF0, 0x00, 0x08, 0x29, 0x46, 0x01, 0x98, 0x12, 0xF0, 0x59, 0xF8, + 0x00, 0x98, 0x30, 0xF8, 0x14, 0x10, 0x0E, 0x98, 0x20, 0xF8, 0x14, 0x10, 0x23, 0xE0, 0x0B, 0xF8, + 0x04, 0x60, 0xD9, 0xF8, 0x1C, 0x10, 0x41, 0xF0, 0x08, 0x01, 0xC9, 0xF8, 0x1C, 0x10, 0x1A, 0xE0, + 0x0E, 0x98, 0x30, 0xF9, 0x14, 0x00, 0x00, 0x28, 0x13, 0xDD, 0x40, 0x1A, 0xA2, 0xEB, 0x01, 0x01, + 0x00, 0xD5, 0x40, 0x42, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, 0x88, 0x42, 0x09, 0xDC, 0x29, 0x46, + 0x01, 0x98, 0x12, 0xF0, 0x34, 0xF8, 0x40, 0x1E, 0xC2, 0xB2, 0x29, 0x46, 0x01, 0x98, 0x12, 0xF0, + 0x30, 0xF8, 0x0B, 0xF8, 0x04, 0x60, 0x64, 0x1C, 0x6D, 0x1C, 0xBC, 0x42, 0xAE, 0xDB, 0x40, 0x46, + 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, + 0x9A, 0x46, 0x17, 0x46, 0x25, 0x46, 0x46, 0x46, 0xDF, 0xF8, 0x2C, 0x91, 0xDD, 0xF8, 0x38, 0xB0, + 0x31, 0xE0, 0x00, 0xBF, 0x0A, 0xEB, 0xE5, 0x00, 0x05, 0xF0, 0x07, 0x02, 0x01, 0x78, 0x06, 0xFA, + 0x02, 0xF0, 0x08, 0x42, 0x26, 0xD0, 0x1B, 0xF8, 0x04, 0x00, 0x01, 0x28, 0x21, 0xD0, 0x00, 0x98, + 0x30, 0xF9, 0x14, 0x10, 0xB9, 0xF9, 0x0E, 0x00, 0x81, 0x42, 0x1A, 0xDD, 0x29, 0x46, 0x01, 0x98, + 0x11, 0xF0, 0xFD, 0xFF, 0x00, 0x28, 0x0C, 0xDD, 0x4F, 0xF0, 0x00, 0x08, 0x04, 0x28, 0x01, 0xDB, + 0x00, 0x1F, 0x00, 0xE0, 0x00, 0x20, 0xC2, 0xB2, 0x29, 0x46, 0x01, 0x98, 0x11, 0xF0, 0xF1, 0xFF, + 0x07, 0xE0, 0x0B, 0xF8, 0x04, 0x60, 0xD9, 0xF8, 0x1C, 0x10, 0x41, 0xF0, 0x04, 0x01, 0xC9, 0xF8, + 0x1C, 0x10, 0x64, 0x1C, 0x6D, 0x1C, 0xBC, 0x42, 0xCC, 0xDB, 0x40, 0x46, 0xB8, 0xE7, 0x2D, 0xE9, + 0xF0, 0x4F, 0x93, 0xB0, 0x00, 0x24, 0x25, 0x46, 0x18, 0x21, 0x0C, 0xA8, 0x13, 0xF0, 0x53, 0xFE, + 0x28, 0x21, 0x02, 0xA8, 0x13, 0xF0, 0x4F, 0xFE, 0x27, 0x48, 0x41, 0x69, 0x00, 0x29, 0x00, 0xDC, + 0x01, 0x24, 0x82, 0x69, 0x00, 0x2A, 0x00, 0xDC, 0x01, 0x25, 0x23, 0x4A, 0x81, 0x46, 0x06, 0x46, + 0xFF, 0x23, 0x50, 0x32, 0x80, 0x6B, 0x00, 0xF0, 0x03, 0xFC, 0x1F, 0x4A, 0xFF, 0x23, 0x58, 0x32, + 0xB1, 0x69, 0xF0, 0x6B, 0x00, 0xF0, 0xFC, 0xFB, 0xFF, 0xF7, 0x77, 0xFD, 0xFF, 0xF7, 0x12, 0xFC, + 0x4F, 0xF4, 0x80, 0x6A, 0x50, 0x46, 0x0D, 0xF0, 0xC2, 0xFA, 0x8C, 0xB1, 0xD9, 0xF8, 0x20, 0x00, + 0x15, 0x4A, 0x4E, 0x46, 0x00, 0x68, 0x0C, 0xAB, 0x50, 0x32, 0xD9, 0xF8, 0x14, 0x10, 0xFF, 0xF7, + 0xF8, 0xFE, 0x01, 0x28, 0x04, 0xD1, 0xF0, 0x69, 0x01, 0x24, 0x40, 0xF0, 0x08, 0x00, 0xF0, 0x61, + 0x8D, 0xB1, 0xD9, 0xF8, 0x24, 0x00, 0x0C, 0x4A, 0x4E, 0x46, 0x00, 0x68, 0x02, 0xAB, 0x58, 0x32, + 0xD9, 0xF8, 0x18, 0x10, 0xFF, 0xF7, 0xE5, 0xFE, 0x01, 0x28, 0x04, 0xD1, 0xF0, 0x69, 0x01, 0x25, + 0x40, 0xF0, 0x08, 0x00, 0xF0, 0x61, 0x0C, 0xB1, 0x00, 0x2D, 0x79, 0xD1, 0x26, 0x46, 0xA8, 0x46, + 0x00, 0x27, 0x7E, 0xB9, 0x0C, 0xA8, 0x01, 0xE0, 0x68, 0x04, 0x10, 0x00, 0x00, 0x90, 0xD9, 0xF8, + 0x20, 0x00, 0xFD, 0x4B, 0xD9, 0xF8, 0x14, 0x20, 0x00, 0x68, 0xD9, 0xF8, 0x38, 0x10, 0xFF, 0xF7, + 0x52, 0xFF, 0x06, 0x46, 0xB8, 0xF1, 0x00, 0x0F, 0x0D, 0xD1, 0x02, 0xA8, 0x00, 0x90, 0xD9, 0xF8, + 0x24, 0x10, 0xF5, 0x4B, 0xD9, 0xF8, 0x18, 0x20, 0x08, 0x68, 0x08, 0x33, 0xD9, 0xF8, 0x3C, 0x10, + 0xFF, 0xF7, 0x41, 0xFF, 0x80, 0x46, 0xFF, 0xF7, 0x20, 0xFD, 0xFF, 0xF7, 0xBB, 0xFB, 0x50, 0x46, + 0x0D, 0xF0, 0x6D, 0xFA, 0x16, 0xB1, 0xB8, 0xF1, 0x00, 0x0F, 0x02, 0xD1, 0x7F, 0x1C, 0x60, 0x2F, + 0xCF, 0xDB, 0xDF, 0xF8, 0xA8, 0xB3, 0xD9, 0xF8, 0x14, 0x00, 0x26, 0x46, 0x41, 0x00, 0x0B, 0xF5, + 0xE6, 0x68, 0x4C, 0x46, 0x58, 0x46, 0x13, 0xF0, 0xA4, 0xFD, 0xA0, 0x69, 0x41, 0x00, 0x40, 0x46, + 0x13, 0xF0, 0x9F, 0xFD, 0x00, 0x27, 0xD1, 0x46, 0xFF, 0xF7, 0x9C, 0xFB, 0x48, 0x46, 0x0D, 0xF0, + 0x4E, 0xFA, 0x56, 0xB9, 0x0C, 0xA8, 0xCD, 0xE9, 0x00, 0xB0, 0x20, 0x6A, 0xDA, 0x4B, 0x62, 0x69, + 0x00, 0x68, 0xA1, 0x6B, 0xFF, 0xF7, 0xAC, 0xFE, 0x06, 0x46, 0x5D, 0xB9, 0x02, 0xA9, 0xCD, 0xE9, + 0x00, 0x81, 0x60, 0x6A, 0xD4, 0x4B, 0xA2, 0x69, 0x00, 0x68, 0x08, 0x33, 0xE1, 0x6B, 0xFF, 0xF7, + 0x9F, 0xFE, 0x05, 0x46, 0xFF, 0xF7, 0xE1, 0xFC, 0xFF, 0xF7, 0x7C, 0xFB, 0x48, 0x46, 0x0D, 0xF0, + 0x2E, 0xFA, 0x06, 0xB1, 0x15, 0xB9, 0x7F, 0x1C, 0x60, 0x2F, 0xD5, 0xDB, 0x01, 0x2E, 0x07, 0xD1, + 0x01, 0x2D, 0x05, 0xD1, 0xE0, 0x69, 0x81, 0x05, 0x02, 0xD5, 0x20, 0xF4, 0x00, 0x70, 0xE0, 0x61, + 0x13, 0xB0, 0xAC, 0xE4, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x46, 0xC3, 0x49, 0x16, 0x46, 0x02, 0x46, + 0x50, 0x39, 0xDD, 0xE9, 0x06, 0x05, 0xB1, 0xF9, 0x10, 0xC0, 0x01, 0x24, 0x62, 0x45, 0x11, 0xDD, + 0x1D, 0x68, 0xA0, 0xF1, 0x7F, 0x02, 0x95, 0x42, 0x07, 0xDD, 0x2A, 0x1A, 0x31, 0x46, 0x38, 0x46, + 0x1A, 0x60, 0x11, 0xF0, 0xCE, 0xFE, 0x00, 0x24, 0x11, 0xE0, 0xC8, 0x69, 0x40, 0xF0, 0x40, 0x00, + 0xC8, 0x61, 0x0C, 0xE0, 0x01, 0x21, 0x29, 0x70, 0x19, 0x68, 0xC0, 0xF1, 0x7F, 0x02, 0x91, 0x42, + 0x05, 0xDA, 0x0A, 0x18, 0x31, 0x46, 0x38, 0x46, 0x1A, 0x60, 0x11, 0xF0, 0xBA, 0xFE, 0x20, 0x46, + 0x43, 0xE5, 0x2D, 0xE9, 0xFF, 0x4F, 0x00, 0x24, 0x85, 0xB0, 0x15, 0x46, 0x06, 0x46, 0xA0, 0x46, + 0xA3, 0x46, 0x8B, 0xE0, 0x08, 0x98, 0x08, 0xF0, 0x07, 0x01, 0x00, 0xEB, 0xE8, 0x00, 0x7F, 0x22, + 0x03, 0x78, 0x01, 0x20, 0x88, 0x40, 0x18, 0x42, 0x03, 0x92, 0x7D, 0xD0, 0x41, 0x46, 0x06, 0x98, + 0x11, 0xF0, 0x9F, 0xFE, 0x00, 0x20, 0xDF, 0xF8, 0x80, 0xA2, 0x8D, 0xF8, 0x08, 0x00, 0x81, 0x46, + 0xAA, 0xF1, 0x50, 0x0A, 0xFF, 0xF7, 0x16, 0xFB, 0xDA, 0xF8, 0x14, 0x00, 0x85, 0x42, 0x03, 0xD1, + 0x4F, 0xF4, 0x00, 0x60, 0x0D, 0xF0, 0xC3, 0xF9, 0x02, 0xAF, 0x10, 0x20, 0xCD, 0xE9, 0x00, 0x07, + 0x36, 0xF9, 0x14, 0x00, 0x03, 0xAB, 0x42, 0x46, 0x06, 0x99, 0xFF, 0xF7, 0x9B, 0xFF, 0x20, 0xB9, + 0x09, 0xF1, 0x01, 0x09, 0xB9, 0xF1, 0x18, 0x0F, 0xE4, 0xDB, 0x9D, 0xF8, 0x08, 0x00, 0xE8, 0xB3, + 0x00, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x81, 0x46, 0xFF, 0xF7, 0xF4, 0xFA, 0xDA, 0xF8, 0x14, 0x00, + 0x85, 0x42, 0x03, 0xD1, 0x4F, 0xF4, 0x00, 0x60, 0x0D, 0xF0, 0xA1, 0xF9, 0x04, 0x20, 0xCD, 0xE9, + 0x00, 0x07, 0x36, 0xF9, 0x14, 0x00, 0x03, 0xAB, 0x42, 0x46, 0x06, 0x99, 0xFF, 0xF7, 0x7A, 0xFF, + 0x20, 0xB9, 0x09, 0xF1, 0x01, 0x09, 0xB9, 0xF1, 0x18, 0x0F, 0xE5, 0xDB, 0x9D, 0xF8, 0x08, 0x00, + 0xE0, 0xB1, 0x00, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x81, 0x46, 0x4F, 0xF0, 0x01, 0x0A, 0x00, 0xBF, + 0xFF, 0xF7, 0xD0, 0xFA, 0x78, 0x48, 0x50, 0x38, 0x40, 0x69, 0x85, 0x42, 0x03, 0xD1, 0x4F, 0xF4, + 0x00, 0x60, 0x0D, 0xF0, 0x7C, 0xF9, 0xCD, 0xE9, 0x00, 0xA7, 0x36, 0xF9, 0x14, 0x00, 0x03, 0xAB, + 0x42, 0x46, 0x06, 0x99, 0xFF, 0xF7, 0x56, 0xFF, 0x80, 0xB1, 0x01, 0xE0, 0x0D, 0xE0, 0x13, 0xE0, + 0x9D, 0xF8, 0x08, 0x00, 0x01, 0x28, 0x0E, 0xD0, 0x03, 0x9A, 0x41, 0x46, 0x52, 0x1E, 0x03, 0x92, + 0x06, 0x98, 0x11, 0xF0, 0x2E, 0xFE, 0x0B, 0xF1, 0x01, 0x0B, 0x04, 0xE0, 0x09, 0xF1, 0x01, 0x09, + 0xB9, 0xF1, 0x18, 0x0F, 0xD4, 0xDB, 0x64, 0x1C, 0x08, 0xF1, 0x01, 0x08, 0xAC, 0x42, 0xFF, 0xF6, + 0x71, 0xAF, 0xAB, 0x45, 0x02, 0xD0, 0x00, 0x20, 0x09, 0xB0, 0xB8, 0xE5, 0x01, 0x20, 0xFB, 0xE7, + 0x2D, 0xE9, 0xFF, 0x5F, 0xDF, 0xF8, 0x70, 0x91, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0x25, 0x9A, 0x46, + 0x17, 0x46, 0x2C, 0x46, 0xA9, 0xF1, 0x50, 0x09, 0x46, 0x46, 0xDD, 0xF8, 0x3C, 0xB0, 0x39, 0xE0, + 0x0A, 0xEB, 0xE4, 0x00, 0x04, 0xF0, 0x07, 0x02, 0x01, 0x78, 0x06, 0xFA, 0x02, 0xF0, 0x08, 0x42, + 0x2F, 0xD0, 0x1B, 0xF8, 0x04, 0x00, 0x58, 0xBB, 0x21, 0x46, 0x01, 0x98, 0x11, 0xF0, 0xF2, 0xFD, + 0x00, 0x99, 0xB9, 0xF9, 0x10, 0x20, 0x31, 0xF9, 0x15, 0x30, 0x49, 0x46, 0x93, 0x42, 0x12, 0xDD, + 0x0E, 0x9A, 0x7F, 0x3A, 0x90, 0x42, 0x08, 0xDD, 0x0E, 0x99, 0x42, 0x1A, 0x21, 0x46, 0x01, 0x98, + 0x11, 0xF0, 0xE7, 0xFD, 0x4F, 0xF0, 0x00, 0x08, 0x12, 0xE0, 0xC8, 0x69, 0x40, 0xF0, 0x40, 0x00, + 0xC9, 0xF8, 0x1C, 0x00, 0x0C, 0xE0, 0x0B, 0xF8, 0x04, 0x60, 0x0E, 0x99, 0xC1, 0xF1, 0x7F, 0x01, + 0x81, 0x42, 0x05, 0xDD, 0x0E, 0x99, 0x42, 0x18, 0x21, 0x46, 0x01, 0x98, 0x11, 0xF0, 0xD1, 0xFD, + 0x6D, 0x1C, 0x64, 0x1C, 0xBD, 0x42, 0xC3, 0xDB, 0x40, 0x46, 0xC9, 0xE5, 0x2D, 0xE9, 0xF0, 0x4F, + 0x35, 0x4C, 0x9D, 0xB0, 0x50, 0x3C, 0x61, 0x69, 0xB1, 0xB3, 0x00, 0x20, 0x83, 0x46, 0xA0, 0x69, + 0x98, 0xB3, 0x00, 0x20, 0x82, 0x46, 0xBB, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0xBA, 0xF1, 0x00, 0x0F, + 0x58, 0xD1, 0x2F, 0x4B, 0x04, 0xAD, 0x0D, 0xCB, 0x85, 0xE8, 0x0D, 0x00, 0x7F, 0x23, 0x2A, 0x4A, + 0x20, 0x6C, 0x00, 0xF0, 0x15, 0xFA, 0x28, 0x4A, 0x7F, 0x23, 0x08, 0x32, 0xA1, 0x69, 0x60, 0x6C, + 0x00, 0xF0, 0x0E, 0xFA, 0x00, 0x26, 0xA1, 0x46, 0x04, 0xA8, 0x5C, 0x46, 0x50, 0xF8, 0x26, 0x80, + 0x55, 0x46, 0x18, 0x21, 0x11, 0xA8, 0x13, 0xF0, 0x3E, 0xFC, 0x28, 0x21, 0x07, 0xA8, 0x13, 0xF0, + 0x3A, 0xFC, 0xD9, 0xF8, 0x1C, 0x10, 0x00, 0x27, 0x21, 0xF0, 0x40, 0x01, 0xC9, 0xF8, 0x1C, 0x10, + 0xFF, 0xF7, 0x10, 0xFA, 0x34, 0xB1, 0x13, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0x20, 0xC5, 0xE7, + 0x01, 0x20, 0xC7, 0xE7, 0x11, 0xA9, 0xCD, 0xE9, 0x00, 0x81, 0xD9, 0xF8, 0x20, 0x10, 0x12, 0x4B, + 0xD9, 0xF8, 0x14, 0x20, 0x08, 0x68, 0xD9, 0xF8, 0x40, 0x10, 0xFF, 0xF7, 0x61, 0xFF, 0x04, 0x46, + 0x75, 0xB9, 0x07, 0xA9, 0xCD, 0xE9, 0x00, 0x81, 0xD9, 0xF8, 0x24, 0x10, 0x0A, 0x4B, 0xD9, 0xF8, + 0x18, 0x20, 0x08, 0x68, 0x08, 0x33, 0xD9, 0xF8, 0x44, 0x10, 0xFF, 0xF7, 0x51, 0xFF, 0x05, 0x46, + 0xFF, 0xF7, 0x4B, 0xFB, 0x04, 0xB1, 0x15, 0xB9, 0x7F, 0x1C, 0x18, 0x2F, 0xD0, 0xDB, 0x76, 0x1C, + 0x03, 0x2E, 0xB9, 0xD3, 0x1D, 0xB0, 0xFA, 0xE4, 0xB8, 0x04, 0x10, 0x00, 0x84, 0x5A, 0x10, 0x00, + 0x0C, 0x6B, 0x01, 0x00, 0x70, 0xB5, 0xFF, 0x4C, 0x00, 0x26, 0x05, 0x46, 0xE6, 0x61, 0x01, 0x28, + 0x5E, 0xD0, 0x02, 0x2D, 0x5E, 0xD0, 0x01, 0x20, 0x20, 0x70, 0x60, 0x79, 0x68, 0xB1, 0xF9, 0x4A, + 0x00, 0x23, 0x50, 0x32, 0x61, 0x69, 0xA0, 0x6B, 0x00, 0xF0, 0xAA, 0xF9, 0xF5, 0x4A, 0x00, 0x23, + 0x58, 0x32, 0xA1, 0x69, 0xE0, 0x6B, 0x00, 0xF0, 0xA3, 0xF9, 0xA0, 0x79, 0x58, 0xB1, 0xF1, 0x49, + 0x62, 0x69, 0x50, 0x31, 0x20, 0x6C, 0x11, 0xF0, 0x3F, 0xFD, 0xEE, 0x49, 0xA2, 0x69, 0x58, 0x31, + 0x60, 0x6C, 0x11, 0xF0, 0x39, 0xFD, 0xE0, 0x78, 0x10, 0xB1, 0x00, 0x20, 0xFF, 0xF7, 0xEE, 0xFB, + 0x20, 0x79, 0x60, 0xB1, 0xE0, 0x78, 0x38, 0xB1, 0x61, 0x78, 0xA0, 0x6A, 0x00, 0xF0, 0x76, 0xF9, + 0x61, 0x78, 0xE0, 0x6A, 0x00, 0xF0, 0x72, 0xF9, 0x01, 0x20, 0xFF, 0xF7, 0xDF, 0xFB, 0x60, 0x79, + 0x08, 0xB1, 0xFF, 0xF7, 0x5C, 0xFD, 0x01, 0x2D, 0x26, 0xD0, 0x02, 0x2D, 0x26, 0xD0, 0x26, 0x70, + 0xFF, 0xF7, 0x90, 0xF9, 0xA0, 0x79, 0x68, 0xB1, 0x20, 0x79, 0x38, 0xB1, 0xA1, 0x78, 0x20, 0x6B, + 0x00, 0xF0, 0x5C, 0xF9, 0xA1, 0x78, 0x60, 0x6B, 0x00, 0xF0, 0x58, 0xF9, 0x20, 0x7A, 0xC0, 0xB1, + 0xFF, 0xF7, 0x34, 0xFF, 0xFF, 0xF7, 0x7E, 0xF9, 0x01, 0x2D, 0x27, 0xD0, 0x02, 0x2D, 0x27, 0xD0, + 0x10, 0x21, 0xE0, 0x69, 0x00, 0xF0, 0x72, 0xF9, 0xE0, 0x69, 0x20, 0xB3, 0x00, 0x20, 0x70, 0xBD, + 0x03, 0x20, 0xA1, 0xE7, 0x05, 0x20, 0x9F, 0xE7, 0x02, 0x20, 0x00, 0xE0, 0x04, 0x20, 0x20, 0x70, + 0xD6, 0xE7, 0xA2, 0x69, 0x00, 0x2A, 0x06, 0xDD, 0x60, 0x6A, 0xC6, 0x4B, 0x61, 0x6C, 0x00, 0x68, + 0x58, 0x33, 0xFF, 0xF7, 0x26, 0xFE, 0x62, 0x69, 0x00, 0x2A, 0xDB, 0xDD, 0x20, 0x6A, 0xC1, 0x4B, + 0x21, 0x6C, 0x00, 0x68, 0x50, 0x33, 0xFF, 0xF7, 0x1C, 0xFE, 0xD3, 0xE7, 0x40, 0x21, 0xD8, 0xE7, + 0x4F, 0xF4, 0x00, 0x71, 0xD5, 0xE7, 0x01, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0xB9, 0x4D, 0x0C, 0x46, + 0x02, 0x28, 0x28, 0xD0, 0x10, 0xF0, 0x21, 0xFE, 0xC5, 0xE9, 0x14, 0x01, 0x10, 0xF0, 0x1F, 0xFE, + 0xC5, 0xE9, 0x16, 0x01, 0xB3, 0x48, 0x08, 0x21, 0x50, 0x30, 0x11, 0xF0, 0xFB, 0xFF, 0x68, 0x61, + 0xB0, 0x48, 0x08, 0x21, 0x58, 0x30, 0x11, 0xF0, 0xF5, 0xFF, 0xA8, 0x61, 0x04, 0xF1, 0x90, 0x00, + 0xA8, 0x62, 0x40, 0x1C, 0xE8, 0x62, 0x40, 0x1C, 0x28, 0x63, 0x40, 0x1C, 0x68, 0x63, 0x4B, 0x38, + 0xA8, 0x63, 0x20, 0x30, 0xC5, 0xE9, 0x0F, 0x04, 0x48, 0x38, 0x68, 0x64, 0x74, 0x30, 0x95, 0x34, + 0xC5, 0xE9, 0x12, 0x04, 0x70, 0xBD, 0x10, 0xF0, 0xFC, 0xFD, 0xC5, 0xE9, 0x14, 0x01, 0x10, 0xF0, + 0xFA, 0xFD, 0xD5, 0xE7, 0x10, 0xB5, 0xA0, 0x49, 0x00, 0x20, 0xFF, 0xF7, 0xC6, 0xFF, 0x9D, 0x48, + 0x9E, 0x49, 0x01, 0x62, 0x09, 0x1D, 0x41, 0x62, 0x9D, 0x49, 0x0B, 0x68, 0x93, 0xF8, 0x88, 0x21, + 0x12, 0xF0, 0x01, 0x04, 0xC4, 0x70, 0x4F, 0xF0, 0x00, 0x02, 0x04, 0xD0, 0x83, 0x6A, 0x1A, 0x70, + 0xC3, 0x6A, 0x1A, 0x70, 0x08, 0xE0, 0x84, 0x6A, 0x93, 0xF8, 0x92, 0x31, 0x23, 0x70, 0x0B, 0x68, + 0xC4, 0x6A, 0x93, 0xF8, 0x93, 0x31, 0x23, 0x70, 0x0C, 0x68, 0x94, 0xF8, 0x88, 0x31, 0xC3, 0xF3, + 0x40, 0x03, 0x03, 0x71, 0x13, 0xB1, 0x03, 0x6B, 0x1A, 0x70, 0x06, 0xE0, 0x03, 0x6B, 0x94, 0xF8, + 0x94, 0x21, 0x1A, 0x70, 0x0A, 0x68, 0x92, 0xF8, 0x95, 0x21, 0x43, 0x6B, 0x1A, 0x70, 0x09, 0x68, + 0x91, 0xF8, 0x88, 0x21, 0xC2, 0xF3, 0x80, 0x03, 0x43, 0x71, 0xC2, 0xF3, 0xC0, 0x03, 0x83, 0x71, + 0xB1, 0xF8, 0x8A, 0x31, 0x43, 0x81, 0xB1, 0xF8, 0x8C, 0x31, 0x83, 0x81, 0xB1, 0xF8, 0x8E, 0x31, + 0xC3, 0x81, 0xB1, 0xF8, 0x90, 0x31, 0x03, 0x82, 0x91, 0xF8, 0x96, 0x31, 0x43, 0x70, 0x91, 0xF8, + 0x97, 0x31, 0x83, 0x70, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0x71, 0x91, 0xF8, 0x34, 0x11, 0xC1, 0xF3, + 0x40, 0x01, 0x01, 0x72, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0xE3, 0xE6, 0x72, 0x49, 0x10, 0xB5, + 0x98, 0x31, 0x01, 0x20, 0xFF, 0xF7, 0x69, 0xFF, 0x70, 0x49, 0x6E, 0x48, 0x10, 0x31, 0x01, 0x62, + 0x00, 0x21, 0xC0, 0xE9, 0x16, 0x11, 0x0A, 0x46, 0x81, 0x61, 0x6D, 0x49, 0x0B, 0x68, 0x93, 0xF8, + 0xA0, 0x41, 0x14, 0xF0, 0x01, 0x04, 0xC4, 0x70, 0x04, 0xD0, 0x83, 0x6A, 0x1A, 0x70, 0xC3, 0x6A, + 0x1A, 0x70, 0x08, 0xE0, 0x84, 0x6A, 0x93, 0xF8, 0xAA, 0x31, 0x23, 0x70, 0x0B, 0x68, 0xC4, 0x6A, + 0x93, 0xF8, 0xAB, 0x31, 0x23, 0x70, 0x0B, 0x68, 0x93, 0xF8, 0xA0, 0x41, 0xC4, 0xF3, 0x40, 0x04, + 0x04, 0x71, 0x14, 0xB1, 0x03, 0x6B, 0x1A, 0x70, 0x06, 0xE0, 0x93, 0xF8, 0xAC, 0x21, 0x03, 0x6B, + 0x1A, 0x70, 0x0A, 0x68, 0x92, 0xF8, 0xAD, 0x21, 0x43, 0x6B, 0x1A, 0x70, 0x09, 0x68, 0x91, 0xF8, + 0xA0, 0x21, 0xC2, 0xF3, 0x80, 0x03, 0x43, 0x71, 0xC2, 0xF3, 0xC0, 0x03, 0x83, 0x71, 0xB1, 0xF8, + 0xA2, 0x31, 0x43, 0x81, 0xB1, 0xF8, 0xA4, 0x31, 0x83, 0x81, 0xB1, 0xF8, 0xA6, 0x31, 0xC3, 0x81, + 0xB1, 0xF8, 0xA8, 0x31, 0x03, 0x82, 0x91, 0xF8, 0xAE, 0x31, 0x43, 0x70, 0x91, 0xF8, 0xAF, 0x31, + 0x83, 0x70, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0x71, 0x91, 0xF8, 0x84, 0x19, 0xC1, 0xF3, 0x40, 0x01, + 0x01, 0x72, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0x84, 0xE6, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, + 0x01, 0x24, 0x00, 0x20, 0x11, 0xF0, 0xE7, 0xF9, 0x02, 0x20, 0x11, 0xF0, 0xE4, 0xF9, 0x41, 0x4E, + 0x78, 0x07, 0x4F, 0xF0, 0x00, 0x05, 0x4F, 0xF0, 0xA5, 0x08, 0x0A, 0xD5, 0xFF, 0xF7, 0x32, 0xFF, + 0x10, 0xF0, 0x01, 0x04, 0x05, 0xD0, 0x30, 0x68, 0xC5, 0x77, 0x80, 0xF8, 0x20, 0x50, 0x80, 0xF8, + 0x1E, 0x80, 0x38, 0x07, 0x0A, 0xD5, 0xFF, 0xF7, 0x81, 0xFF, 0x20, 0x40, 0x04, 0x00, 0x05, 0xD0, + 0x30, 0x68, 0x00, 0xF8, 0x22, 0x5F, 0x45, 0x70, 0x00, 0xF8, 0x01, 0x8C, 0x02, 0x20, 0x11, 0xF0, + 0xDD, 0xF9, 0x00, 0x20, 0x11, 0xF0, 0xDA, 0xF9, 0x20, 0x46, 0xF1, 0xE4, 0x02, 0x78, 0x8A, 0x42, + 0x01, 0xD9, 0x51, 0x1A, 0x00, 0xE0, 0x00, 0x21, 0x01, 0x70, 0x70, 0x47, 0x10, 0xB5, 0x14, 0x46, + 0x0E, 0xF0, 0x0F, 0xFE, 0xA0, 0x42, 0x01, 0xDC, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, + 0xF0, 0xB5, 0x00, 0x25, 0x2C, 0x46, 0x01, 0x26, 0x0D, 0xE0, 0x00, 0xBF, 0x02, 0xEB, 0xE4, 0x07, + 0x04, 0xF0, 0x07, 0x0C, 0x3F, 0x78, 0x06, 0xFA, 0x0C, 0xFE, 0x1E, 0xEA, 0x07, 0x0F, 0x01, 0xD0, + 0x03, 0x55, 0x6D, 0x1C, 0x64, 0x1C, 0x8D, 0x42, 0xF0, 0xDB, 0xF0, 0xBD, 0x70, 0xB5, 0x04, 0x46, + 0x0D, 0x46, 0xC0, 0x07, 0x02, 0xD0, 0x83, 0x20, 0x0C, 0xF0, 0x16, 0xFF, 0xA0, 0x07, 0x03, 0xD5, + 0x29, 0x46, 0x84, 0x20, 0x0C, 0xF0, 0x10, 0xFF, 0x60, 0x07, 0x03, 0xD5, 0x29, 0x46, 0x85, 0x20, + 0x0C, 0xF0, 0x0A, 0xFF, 0x20, 0x07, 0x03, 0xD5, 0x29, 0x46, 0x86, 0x20, 0x0C, 0xF0, 0x04, 0xFF, + 0x60, 0x06, 0x03, 0xD5, 0x29, 0x46, 0x8B, 0x20, 0x0C, 0xF0, 0xFE, 0xFE, 0x20, 0x06, 0x03, 0xD5, + 0x29, 0x46, 0x8C, 0x20, 0x0C, 0xF0, 0xF8, 0xFE, 0xE0, 0x05, 0x0F, 0xD5, 0x29, 0x46, 0x87, 0x20, + 0x0A, 0xE0, 0x00, 0x00, 0x68, 0x04, 0x10, 0x00, 0xEC, 0x57, 0x01, 0x20, 0x14, 0x0A, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0x0C, 0xF0, 0xE6, 0xFE, 0xA0, 0x05, 0x05, 0xD5, + 0x29, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x88, 0x20, 0x0C, 0xF0, 0xDE, 0xBE, 0x70, 0xBD, 0x00, 0x00, + 0x5C, 0x4E, 0x08, 0xB5, 0x5C, 0x4D, 0x00, 0x24, 0xDF, 0xF8, 0x70, 0x91, 0x34, 0x60, 0xDF, 0xF8, + 0x70, 0x81, 0x2C, 0x60, 0xDF, 0xF8, 0x6C, 0xB1, 0xC9, 0xF8, 0x00, 0x40, 0xDF, 0xF8, 0x68, 0xA1, + 0xC8, 0xF8, 0x00, 0x40, 0xCB, 0xF8, 0x00, 0x40, 0xCA, 0xF8, 0x00, 0x40, 0x00, 0x22, 0x6B, 0x46, + 0x56, 0x49, 0x10, 0x46, 0x11, 0xF0, 0xE0, 0xF8, 0x00, 0x98, 0x81, 0x07, 0x13, 0xD5, 0xFC, 0xF7, + 0x15, 0xFF, 0x2F, 0x68, 0x2C, 0x60, 0xFC, 0xF7, 0x0F, 0xFF, 0x17, 0xF0, 0x53, 0x0F, 0x02, 0xD0, + 0x38, 0x46, 0xFE, 0xF7, 0x72, 0xFE, 0x17, 0xF4, 0xD6, 0x7F, 0x02, 0xD0, 0x38, 0x46, 0xFF, 0xF7, + 0x34, 0xFF, 0x02, 0x21, 0x82, 0xE0, 0xC1, 0x05, 0x0B, 0xD5, 0xFC, 0xF7, 0xFF, 0xFE, 0x37, 0x68, + 0x34, 0x60, 0xFC, 0xF7, 0xF9, 0xFE, 0x38, 0x46, 0xFD, 0xF7, 0xB4, 0xF8, 0x4F, 0xF4, 0x80, 0x71, + 0x74, 0xE0, 0x81, 0x05, 0x04, 0xD5, 0xFE, 0xF7, 0xA6, 0xF9, 0x4F, 0xF4, 0x00, 0x71, 0x6D, 0xE0, + 0x41, 0x05, 0x16, 0xD5, 0xFC, 0xF7, 0xEA, 0xFE, 0xD8, 0xF8, 0x00, 0x70, 0xC8, 0xF8, 0x00, 0x40, + 0xFC, 0xF7, 0xE2, 0xFE, 0xF8, 0x07, 0x01, 0xD0, 0xFD, 0xF7, 0x94, 0xFD, 0xB8, 0x07, 0x01, 0xD5, + 0xFD, 0xF7, 0x09, 0xFE, 0x78, 0x07, 0x01, 0xD5, 0xFD, 0xF7, 0xA0, 0xFD, 0x4F, 0xF4, 0x80, 0x61, + 0x54, 0xE0, 0x01, 0x06, 0x0C, 0xD5, 0xFC, 0xF7, 0xD1, 0xFE, 0xDB, 0xF8, 0x00, 0x70, 0xCB, 0xF8, + 0x00, 0x40, 0xFC, 0xF7, 0xC9, 0xFE, 0x38, 0x46, 0xFE, 0xF7, 0x11, 0xF8, 0x80, 0x21, 0x45, 0xE0, + 0x81, 0x02, 0x0D, 0xD5, 0xFC, 0xF7, 0xC2, 0xFE, 0xD9, 0xF8, 0x00, 0x70, 0xC9, 0xF8, 0x00, 0x40, + 0xFC, 0xF7, 0xBA, 0xFE, 0x38, 0x46, 0xFD, 0xF7, 0x09, 0xFD, 0x4F, 0xF4, 0x00, 0x11, 0x35, 0xE0, + 0xC1, 0x04, 0x04, 0xD5, 0xFE, 0xF7, 0xD8, 0xFE, 0x4F, 0xF4, 0x80, 0x51, 0x2E, 0xE0, 0x01, 0x02, + 0x04, 0xD5, 0xFD, 0xF7, 0x4F, 0xFE, 0x4F, 0xF4, 0x00, 0x01, 0x27, 0xE0, 0x01, 0x05, 0x04, 0xD5, + 0xFE, 0xF7, 0xE5, 0xFE, 0x4F, 0xF4, 0x00, 0x61, 0x20, 0xE0, 0x40, 0x02, 0x7F, 0xF5, 0x7E, 0xAF, + 0xFC, 0xF7, 0x9C, 0xFE, 0xDA, 0xF8, 0x00, 0x70, 0xCA, 0xF8, 0x00, 0x40, 0xFC, 0xF7, 0x94, 0xFE, + 0xF8, 0x07, 0x01, 0xD0, 0xFE, 0xF7, 0x47, 0xF9, 0xB8, 0x07, 0x05, 0xD5, 0x01, 0x20, 0xFE, 0xF7, + 0x2B, 0xFD, 0x01, 0x20, 0xFF, 0xF7, 0x5D, 0xF8, 0x78, 0x07, 0x05, 0xD5, 0x00, 0x20, 0xFE, 0xF7, + 0x23, 0xFD, 0x00, 0x20, 0xFF, 0xF7, 0x55, 0xF8, 0x4F, 0xF4, 0x80, 0x01, 0x00, 0x20, 0x11, 0xF0, + 0x26, 0xF8, 0x5B, 0xE7, 0x28, 0x07, 0x10, 0x00, 0x2C, 0x07, 0x10, 0x00, 0x30, 0x07, 0x10, 0x00, + 0x34, 0x07, 0x10, 0x00, 0x38, 0x07, 0x10, 0x00, 0x3C, 0x07, 0x10, 0x00, 0x83, 0x9F, 0xF0, 0x00, + 0x20, 0x48, 0x10, 0xB5, 0x01, 0x68, 0x20, 0x48, 0x02, 0x68, 0x13, 0x46, 0x92, 0xEA, 0x01, 0x0F, + 0x28, 0xD0, 0x1E, 0x4A, 0xCC, 0x07, 0x12, 0x68, 0x25, 0xD0, 0x92, 0xF8, 0x21, 0x43, 0xE4, 0x07, + 0x02, 0xD0, 0x43, 0xF0, 0x01, 0x03, 0x03, 0x60, 0x8B, 0x07, 0x1F, 0xD5, 0x92, 0xF8, 0x40, 0x33, + 0xDB, 0x07, 0x03, 0xD0, 0x03, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x03, 0x60, 0x0B, 0x07, 0x19, 0xD5, + 0x92, 0xF8, 0x60, 0x33, 0xDB, 0x07, 0x03, 0xD0, 0x03, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x03, 0x60, + 0x49, 0x06, 0x13, 0xD5, 0x92, 0xF8, 0x60, 0x13, 0xC9, 0x07, 0x03, 0xD0, 0x01, 0x68, 0x41, 0xF0, + 0x40, 0x01, 0x01, 0x60, 0x10, 0xBD, 0x23, 0xF0, 0x01, 0x03, 0xDC, 0xE7, 0x03, 0x68, 0x23, 0xF0, + 0x02, 0x03, 0xE2, 0xE7, 0x03, 0x68, 0x23, 0xF0, 0x08, 0x03, 0xE8, 0xE7, 0x01, 0x68, 0x21, 0xF0, + 0x40, 0x01, 0xEE, 0xE7, 0x48, 0x07, 0x10, 0x00, 0xF0, 0x04, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x10, 0x92, 0x84, 0x4C, 0x00, 0x25, 0xD9, 0xF8, 0x00, 0x10, + 0x91, 0xF8, 0x31, 0x00, 0x84, 0xF8, 0x30, 0x00, 0x91, 0xF8, 0x30, 0x20, 0x80, 0x49, 0x84, 0xF8, + 0x31, 0x20, 0x50, 0x43, 0x09, 0x78, 0x84, 0xF8, 0x33, 0x10, 0x7E, 0x49, 0x21, 0x60, 0x34, 0x39, + 0x06, 0xB2, 0x8B, 0x7B, 0x84, 0xF8, 0x2D, 0x30, 0x88, 0x46, 0x77, 0x00, 0x0F, 0xE0, 0x2A, 0x46, + 0x31, 0x46, 0xD8, 0xF8, 0x08, 0x00, 0x0D, 0xF0, 0xD6, 0xFD, 0x01, 0x46, 0x22, 0x68, 0x06, 0xFB, + 0x05, 0xF0, 0x02, 0xEB, 0x40, 0x00, 0x3A, 0x46, 0x13, 0xF0, 0x04, 0xF8, 0x6D, 0x1C, 0x94, 0xF8, + 0x2D, 0x00, 0xA8, 0x42, 0xEB, 0xDC, 0x70, 0x48, 0x70, 0x49, 0x00, 0x78, 0x09, 0x78, 0x08, 0x43, + 0x40, 0x07, 0x11, 0xD5, 0x6E, 0x48, 0x60, 0x60, 0xD9, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xF1, 0x11, + 0x89, 0x07, 0x4A, 0x0F, 0x94, 0xF8, 0x31, 0x10, 0x92, 0x1C, 0x4A, 0x43, 0xD8, 0xF8, 0x10, 0x10, + 0xBD, 0xE8, 0xF0, 0x47, 0x12, 0xF0, 0xE6, 0xBF, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x41, + 0x61, 0x48, 0x62, 0x4F, 0x00, 0x26, 0x05, 0x68, 0x38, 0x68, 0x05, 0x43, 0x01, 0x20, 0x10, 0xF0, + 0xEA, 0xFF, 0x38, 0x21, 0x59, 0x48, 0x13, 0xF0, 0x76, 0xF8, 0xE8, 0x07, 0x06, 0xD0, 0xFF, 0xF7, + 0x9F, 0xFF, 0xE8, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0x77, 0xF8, 0x01, 0x26, 0x59, 0x48, 0x53, 0x4C, + 0x00, 0x68, 0xC4, 0xE9, 0x07, 0x05, 0x38, 0x68, 0x60, 0x62, 0x52, 0x48, 0x56, 0x4F, 0x34, 0x38, + 0x41, 0x68, 0xA1, 0x62, 0xC1, 0x7B, 0x84, 0xF8, 0x35, 0x10, 0x90, 0xF8, 0x30, 0x00, 0x84, 0xF8, + 0x36, 0x00, 0x38, 0x78, 0x84, 0xF8, 0x2C, 0x00, 0xE8, 0x07, 0x1A, 0xD0, 0xE8, 0x06, 0x18, 0xD5, + 0x45, 0x4D, 0x28, 0x68, 0x90, 0xF8, 0x50, 0x02, 0xC0, 0x07, 0x06, 0xD0, 0x00, 0xF0, 0x75, 0xFD, + 0x18, 0xB9, 0xE0, 0x69, 0x40, 0xF0, 0x10, 0x00, 0xE0, 0x61, 0x28, 0x68, 0x90, 0xF8, 0x80, 0x02, + 0xC0, 0x07, 0x06, 0xD0, 0x00, 0xF0, 0x69, 0xFD, 0x18, 0xB9, 0xE0, 0x69, 0x40, 0xF0, 0x20, 0x00, + 0xE0, 0x61, 0x01, 0x20, 0x10, 0xF0, 0xC2, 0xFF, 0x00, 0x2E, 0x0C, 0xD0, 0x38, 0x78, 0x05, 0x28, + 0x07, 0xD0, 0x06, 0x28, 0x05, 0xD0, 0x01, 0x21, 0xBD, 0xE8, 0xF0, 0x41, 0x02, 0x20, 0x10, 0xF0, + 0xFA, 0xBE, 0x02, 0x21, 0xF8, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x48, 0x10, 0xB5, 0x00, 0x78, + 0x00, 0x28, 0x28, 0xD1, 0x2F, 0x4C, 0x34, 0x3C, 0xD4, 0xE9, 0x06, 0x01, 0x00, 0xF0, 0x48, 0xFD, + 0x94, 0xF8, 0x31, 0x10, 0xA0, 0x6A, 0x00, 0xF0, 0x40, 0xFC, 0xFF, 0xF7, 0x8F, 0xFF, 0x26, 0x48, + 0x00, 0x68, 0x90, 0xF8, 0x60, 0x03, 0xC1, 0x07, 0x15, 0xD0, 0x81, 0x07, 0x13, 0xD5, 0x00, 0x24, + 0x40, 0x09, 0x13, 0xF0, 0x8B, 0xF8, 0x00, 0xB1, 0x01, 0x24, 0x29, 0x48, 0x01, 0x78, 0x8C, 0x42, + 0x09, 0xD0, 0x04, 0x70, 0x0C, 0xB1, 0x08, 0x21, 0x00, 0xE0, 0x10, 0x21, 0xBD, 0xE8, 0x10, 0x40, + 0x03, 0x20, 0x10, 0xF0, 0xC8, 0xBE, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x16, 0x48, 0x19, 0x4E, + 0x16, 0x4C, 0x00, 0x68, 0x34, 0x3E, 0x90, 0xF8, 0x31, 0x50, 0x90, 0xF8, 0x30, 0x70, 0xB1, 0x69, + 0x39, 0xB1, 0x17, 0x48, 0x84, 0xF8, 0x30, 0x50, 0xC2, 0x38, 0x6A, 0x00, 0x20, 0x61, 0x12, 0xF0, + 0x41, 0xFF, 0xF1, 0x69, 0x39, 0xB1, 0x12, 0x48, 0x84, 0xF8, 0x31, 0x70, 0x98, 0x38, 0x7A, 0x00, + 0x60, 0x61, 0x12, 0xF0, 0x37, 0xFF, 0x0C, 0x48, 0x0C, 0x49, 0x00, 0x78, 0x09, 0x78, 0x08, 0x43, + 0x80, 0x06, 0xA8, 0xD5, 0x0A, 0x48, 0x4C, 0x38, 0xE0, 0x60, 0x6A, 0x00, 0x71, 0x6A, 0xBD, 0xE8, + 0xF0, 0x41, 0x12, 0xF0, 0x27, 0xBF, 0x9E, 0xE7, 0x20, 0x07, 0x10, 0x00, 0x7C, 0x6C, 0x10, 0x00, + 0xFC, 0x04, 0x10, 0x00, 0x64, 0x0A, 0x10, 0x00, 0xF4, 0x04, 0x10, 0x00, 0xF8, 0x04, 0x10, 0x00, + 0xD6, 0x07, 0x01, 0x20, 0xF0, 0x04, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0xE9, 0x04, 0x10, 0x00, + 0xC8, 0x04, 0x10, 0x00, 0x12, 0x48, 0x10, 0xB5, 0x12, 0x49, 0x04, 0x78, 0x00, 0x20, 0x08, 0x60, + 0x00, 0xF0, 0x47, 0xF8, 0x00, 0xF0, 0xEC, 0xFA, 0x05, 0x2C, 0x11, 0xD0, 0x06, 0x2C, 0x0F, 0xD0, + 0x0D, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x02, 0x01, 0x41, 0xF0, 0x04, 0x01, 0x01, 0x60, 0x01, 0x21, + 0x05, 0x20, 0x0C, 0xF0, 0x6F, 0xFF, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x10, 0xF0, 0x63, 0xFE, + 0x00, 0xF0, 0x7D, 0xFD, 0x02, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0x10, 0xF0, 0x5B, 0xBE, + 0xE8, 0x04, 0x10, 0x00, 0xEC, 0x04, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xC0, 0x07, + 0x1E, 0xD0, 0x38, 0x48, 0x03, 0x24, 0x00, 0x68, 0x90, 0xF8, 0x50, 0x12, 0xC9, 0x07, 0x03, 0xD1, + 0x90, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x0B, 0x24, 0xFC, 0xF7, 0xC7, 0xFC, 0x32, 0x48, + 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xFC, 0xF7, 0xBF, 0xFC, 0x01, 0x21, 0x05, 0x20, 0x0C, 0xF0, + 0x41, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x10, 0xF0, 0x33, 0xBE, + 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF0, 0x4B, 0xFD, 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x57, 0xFE, + 0x01, 0x20, 0x10, 0xF0, 0xC8, 0xFE, 0x38, 0x21, 0x24, 0x48, 0x12, 0xF0, 0x54, 0xFF, 0x23, 0x49, + 0x01, 0x20, 0x81, 0xF8, 0x2C, 0x00, 0x10, 0xF0, 0xD9, 0xFE, 0x01, 0x21, 0x02, 0x20, 0x10, 0xF0, + 0x1A, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x84, 0xBA, 0x70, 0xB5, 0x1C, 0x48, 0x1D, 0x4E, + 0x05, 0x68, 0x30, 0x68, 0x90, 0xEA, 0x05, 0x04, 0x1F, 0xD0, 0x35, 0xB1, 0x40, 0xB1, 0x04, 0xEA, + 0x05, 0x00, 0xFF, 0xF7, 0xB3, 0xFF, 0x35, 0x60, 0x70, 0xBD, 0xFF, 0xF7, 0xD2, 0xFF, 0xFA, 0xE7, + 0x00, 0xF0, 0x1D, 0xFD, 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x29, 0xFE, 0x00, 0xF0, 0xDB, 0xF8, + 0x00, 0xF0, 0x5F, 0xFA, 0x04, 0xEA, 0x05, 0x00, 0xFF, 0xF7, 0xA0, 0xFF, 0x00, 0xF0, 0x48, 0xFA, + 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0xEF, 0xFD, 0xE5, 0xE7, 0x00, 0x2D, 0xE4, 0xD1, 0x0A, 0x48, + 0x00, 0x78, 0x05, 0x28, 0x01, 0xD0, 0x06, 0x28, 0xDE, 0xD1, 0x35, 0x60, 0xBD, 0xE8, 0x70, 0x40, + 0xAF, 0xE7, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0x7C, 0x6C, 0x10, 0x00, + 0x44, 0x07, 0x10, 0x00, 0xEC, 0x04, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x70, 0xB5, 0xFB, 0x49, + 0x00, 0x20, 0x03, 0x46, 0x09, 0x68, 0x91, 0xF8, 0x40, 0x20, 0xD2, 0x07, 0x33, 0xD0, 0xF8, 0x4A, + 0x15, 0x78, 0x02, 0x2D, 0x16, 0xD0, 0x04, 0x2D, 0x03, 0xD0, 0x05, 0x2D, 0x0F, 0xD0, 0x06, 0x2D, + 0x0D, 0xD0, 0x91, 0xF8, 0x41, 0x20, 0xF3, 0x49, 0x0C, 0x68, 0x64, 0x1C, 0x0C, 0x60, 0x94, 0x42, + 0x21, 0xDD, 0xF1, 0x4A, 0x00, 0x20, 0x14, 0x78, 0x64, 0xB1, 0x08, 0x60, 0x0C, 0xE0, 0x91, 0xF8, + 0x43, 0x20, 0xF0, 0xE7, 0x91, 0xF8, 0x42, 0x20, 0x91, 0xF8, 0x90, 0x10, 0xC9, 0x06, 0xEA, 0xD5, + 0x01, 0x23, 0xE8, 0xE7, 0x13, 0xB1, 0x01, 0x20, 0x10, 0x70, 0x00, 0xE0, 0x08, 0x60, 0x05, 0x2D, + 0x0A, 0xD0, 0x00, 0xF0, 0xB3, 0xF8, 0x04, 0x46, 0x00, 0xF0, 0xB6, 0xF8, 0x40, 0xEA, 0x04, 0x05, + 0x00, 0xF0, 0xC0, 0xF8, 0x28, 0x43, 0x70, 0xBD, 0x01, 0x20, 0x70, 0xBD, 0x10, 0xB5, 0x01, 0x46, + 0x34, 0x22, 0xDE, 0x48, 0x12, 0xF0, 0x63, 0xFE, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, + 0x10, 0xF0, 0x89, 0xBD, 0x2D, 0xE9, 0xFF, 0x47, 0x81, 0x46, 0xD5, 0x48, 0x01, 0x24, 0x00, 0x78, + 0x02, 0x28, 0x22, 0xD0, 0x03, 0x28, 0x1C, 0xD0, 0x04, 0x25, 0xD5, 0x4E, 0xDF, 0xF8, 0x54, 0x83, + 0x05, 0x28, 0x1E, 0xD0, 0x06, 0x28, 0x68, 0x46, 0x2F, 0xD0, 0x00, 0xF0, 0x11, 0xF9, 0xD2, 0x48, + 0x00, 0x90, 0xCA, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x10, 0xC8, 0x07, 0x38, 0xD0, 0x89, 0x07, + 0x30, 0xD5, 0xCE, 0x49, 0x0A, 0x78, 0x52, 0xB3, 0x00, 0x20, 0x8D, 0xF8, 0x0B, 0x00, 0x08, 0x70, + 0x2E, 0xE0, 0x68, 0x46, 0x00, 0xF0, 0xCD, 0xF8, 0xE9, 0xE7, 0x68, 0x46, 0x00, 0xF0, 0x91, 0xF8, + 0xE5, 0xE7, 0x68, 0x46, 0x10, 0xF0, 0xA2, 0xF8, 0xFF, 0xF7, 0x80, 0xFF, 0x40, 0x21, 0xC2, 0x07, + 0x01, 0xD0, 0x8D, 0xF8, 0x04, 0x50, 0xC2, 0x06, 0x01, 0xD5, 0x8D, 0xF8, 0x06, 0x40, 0x8D, 0xF8, + 0x08, 0x40, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x10, 0xD1, 0xE7, 0x00, 0x27, 0x10, 0xF0, 0x8E, 0xF8, + 0x8D, 0xF8, 0x04, 0x50, 0x01, 0x20, 0x37, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0xC7, 0xE7, 0xB9, 0xF1, + 0x08, 0x0F, 0x02, 0xD9, 0x8D, 0xF8, 0x0B, 0x40, 0x02, 0xE0, 0x02, 0x20, 0x8D, 0xF8, 0x0B, 0x00, + 0x68, 0x46, 0x10, 0xF0, 0xA0, 0xF8, 0xB2, 0x49, 0xB2, 0x4A, 0xC9, 0x78, 0x11, 0x70, 0x04, 0xB0, + 0xBD, 0xE8, 0xF0, 0x87, 0x10, 0xB5, 0x00, 0xF0, 0x42, 0xFC, 0x02, 0x21, 0xBD, 0xE8, 0x10, 0x40, + 0x01, 0x20, 0x10, 0xF0, 0x20, 0xBD, 0xA3, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0xA1, 0x49, + 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x38, 0xB5, 0x00, 0x20, 0x10, 0xF0, 0xB4, 0xFD, 0x00, 0xF0, + 0x94, 0xF9, 0x9B, 0x48, 0x00, 0x78, 0x00, 0xF0, 0xDA, 0xF8, 0x04, 0x46, 0xAF, 0xF2, 0x3B, 0x01, + 0x00, 0xF0, 0x1D, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0x7D, 0xFF, 0x01, 0x28, 0x0E, 0xD1, 0x01, 0x21, + 0x6B, 0x46, 0x00, 0x22, 0x08, 0x46, 0x10, 0xF0, 0x47, 0xFD, 0x01, 0x21, 0x08, 0x46, 0x10, 0xF0, + 0x26, 0xFD, 0x92, 0x48, 0x00, 0x78, 0x30, 0xB1, 0x0C, 0xF0, 0x2D, 0xFB, 0xBD, 0xE8, 0x38, 0x40, + 0x00, 0x20, 0x10, 0xF0, 0xAB, 0xBD, 0xFF, 0xF7, 0xF8, 0xFD, 0xF7, 0xE7, 0x92, 0x48, 0x00, 0x78, + 0xC0, 0x07, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x8F, 0x48, 0x00, 0x78, 0xC0, 0x07, 0x07, 0xD0, + 0x82, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x50, 0x02, 0xC0, 0x07, 0x01, 0xD0, 0x10, 0x20, 0x70, 0x47, + 0x00, 0x20, 0x70, 0x47, 0x88, 0x48, 0x00, 0x78, 0xC1, 0x07, 0x7C, 0x48, 0x00, 0x68, 0x90, 0xF8, + 0x80, 0x02, 0x03, 0xD0, 0xC1, 0x07, 0x01, 0xD0, 0x10, 0x20, 0x70, 0x47, 0x00, 0xF0, 0x01, 0x00, + 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x06, 0x46, 0x00, 0x24, 0x10, 0xF0, 0x0F, 0xF8, 0xFF, 0xF7, + 0xED, 0xFE, 0x05, 0x46, 0x7C, 0x48, 0x00, 0x78, 0xC0, 0x07, 0x00, 0xD0, 0x40, 0x24, 0x6D, 0xB1, + 0x6E, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x90, 0x00, 0x00, 0x07, 0x07, 0xD5, 0x00, 0xF0, 0xAE, 0xF8, + 0x40, 0xEA, 0x04, 0x07, 0x00, 0xF0, 0xB8, 0xF8, 0x40, 0xEA, 0x07, 0x04, 0x45, 0xEA, 0x04, 0x00, + 0xC0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0xBE, 0xF8, 0x30, 0x71, 0x61, 0x07, 0x4F, 0xF0, 0x01, 0x00, + 0x00, 0xD5, 0x70, 0x71, 0xE9, 0x06, 0x00, 0xD5, 0xB0, 0x71, 0x61, 0x06, 0x00, 0xD5, 0x30, 0x72, + 0xA1, 0x06, 0x00, 0xD5, 0xF0, 0x71, 0x62, 0x48, 0x05, 0x60, 0x62, 0x48, 0x04, 0x60, 0xBD, 0xE8, + 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x41, 0x06, 0x46, 0x0F, 0xF0, 0xD8, 0xFF, 0xFF, 0xF7, 0xB6, 0xFE, + 0x07, 0x46, 0xFF, 0xF7, 0x9B, 0xFF, 0x04, 0x46, 0xFF, 0xF7, 0x9E, 0xFF, 0x04, 0x43, 0xFF, 0xF7, + 0xA9, 0xFF, 0x04, 0x43, 0x00, 0xF0, 0x7A, 0xF8, 0x04, 0x43, 0x00, 0xF0, 0x85, 0xF8, 0x40, 0xEA, + 0x04, 0x05, 0x47, 0xEA, 0x05, 0x04, 0xE0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0x8B, 0xF8, 0x30, 0x71, + 0x69, 0x07, 0x4F, 0xF0, 0x01, 0x00, 0x00, 0xD5, 0x70, 0x71, 0xE1, 0x06, 0x00, 0xD5, 0xB0, 0x71, + 0xA9, 0x06, 0x00, 0xD5, 0xF0, 0x71, 0x4A, 0x48, 0x07, 0x60, 0x4A, 0x48, 0x05, 0x60, 0xCE, 0xE7, + 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x0F, 0xF0, 0xA9, 0xFF, 0xFF, 0xF7, 0x87, 0xFE, 0x05, 0x46, + 0xFF, 0xF7, 0x6C, 0xFF, 0x04, 0x46, 0xFF, 0xF7, 0x6F, 0xFF, 0x04, 0x43, 0xFF, 0xF7, 0x7A, 0xFF, + 0x04, 0x43, 0x00, 0xF0, 0x4B, 0xF8, 0x04, 0x43, 0x00, 0xF0, 0x56, 0xF8, 0x40, 0xEA, 0x04, 0x06, + 0x45, 0xEA, 0x06, 0x04, 0xE0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0x5C, 0xF8, 0x38, 0x71, 0x61, 0x07, + 0x4F, 0xF0, 0x01, 0x00, 0x00, 0xD5, 0x78, 0x71, 0xE1, 0x06, 0x00, 0xD5, 0xB8, 0x71, 0xB1, 0x06, + 0x00, 0xD5, 0xF8, 0x71, 0x32, 0x48, 0x05, 0x60, 0x32, 0x48, 0x06, 0x60, 0x9F, 0xE7, 0x38, 0xB5, + 0x2A, 0x49, 0x80, 0x1E, 0x05, 0x28, 0x09, 0x68, 0x13, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x06, + 0x09, 0x0C, 0x0F, 0x00, 0x91, 0xF8, 0x73, 0x40, 0x0C, 0xE0, 0x91, 0xF8, 0x72, 0x40, 0x09, 0xE0, + 0x91, 0xF8, 0x71, 0x40, 0x06, 0xE0, 0x91, 0xF8, 0x74, 0x40, 0x03, 0xE0, 0x91, 0xF8, 0x75, 0x40, + 0x00, 0xE0, 0x01, 0x24, 0x00, 0x25, 0x0B, 0xF0, 0x6B, 0xFE, 0x00, 0xB1, 0x01, 0x25, 0x69, 0x46, + 0x03, 0x20, 0x10, 0xF0, 0x4A, 0xFC, 0x00, 0x98, 0x00, 0xB9, 0x1D, 0xB1, 0x14, 0x2C, 0x01, 0xD2, + 0x14, 0x24, 0x01, 0xE0, 0x04, 0xB9, 0x01, 0x24, 0x20, 0x46, 0x38, 0xBD, 0x1E, 0x48, 0x00, 0x78, + 0xC0, 0x07, 0x07, 0xD0, 0x11, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xF0, 0x01, 0xC0, 0x07, 0x01, 0xD0, + 0x04, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x17, 0x48, 0x00, 0x78, 0xC0, 0x07, 0x07, 0xD0, + 0x0A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x10, 0x02, 0xC0, 0x07, 0x01, 0xD0, 0x20, 0x20, 0x70, 0x47, + 0x00, 0x20, 0x70, 0x47, 0x05, 0x49, 0x01, 0x20, 0x09, 0x68, 0x91, 0xF8, 0xE7, 0x10, 0x09, 0x06, + 0x03, 0xD5, 0x0B, 0x48, 0x40, 0x78, 0xC8, 0xB1, 0x03, 0x20, 0x70, 0x47, 0x20, 0x07, 0x10, 0x00, + 0xE8, 0x04, 0x10, 0x00, 0xCC, 0x04, 0x10, 0x00, 0xE9, 0x04, 0x10, 0x00, 0x30, 0x0A, 0x10, 0x00, + 0xF8, 0x04, 0x10, 0x00, 0xF4, 0x04, 0x10, 0x00, 0x7D, 0x3B, 0x00, 0x00, 0xDB, 0x04, 0x10, 0x00, + 0x4C, 0x07, 0x10, 0x00, 0xFC, 0x04, 0x10, 0x00, 0xEC, 0x04, 0x10, 0x00, 0x02, 0x20, 0xE4, 0xE7, + 0x10, 0xB5, 0x00, 0xF0, 0x9C, 0xF9, 0x00, 0xF0, 0x12, 0xFA, 0x62, 0x49, 0x00, 0x20, 0x48, 0x60, + 0x61, 0x49, 0x02, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF0, 0x90, 0xF9, 0x00, 0xF0, + 0x06, 0xFA, 0x5C, 0x49, 0x00, 0x20, 0x48, 0x60, 0x5B, 0x49, 0x03, 0x20, 0x08, 0x70, 0x10, 0xBD, + 0x10, 0xB5, 0x00, 0xF0, 0x84, 0xF9, 0x00, 0xF0, 0xFA, 0xF9, 0x56, 0x49, 0x00, 0x20, 0x48, 0x60, + 0x55, 0x49, 0x04, 0x20, 0x08, 0x70, 0x55, 0x49, 0x01, 0x20, 0x08, 0x70, 0x54, 0x49, 0x08, 0x70, + 0x10, 0xBD, 0x50, 0x49, 0x00, 0x20, 0x48, 0x60, 0x70, 0x47, 0x4E, 0x49, 0x00, 0x20, 0x48, 0x60, + 0x70, 0x47, 0x4C, 0x49, 0x00, 0x20, 0x48, 0x60, 0x4B, 0x49, 0x01, 0x20, 0x08, 0x70, 0x70, 0x47, + 0x10, 0xB5, 0x00, 0xF0, 0x61, 0xF9, 0x47, 0x49, 0x08, 0x70, 0x00, 0xF0, 0x60, 0xF9, 0x00, 0xF0, + 0xD6, 0xF9, 0x45, 0x49, 0x05, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x70, 0xB5, 0x42, 0x4D, 0x00, 0x26, + 0x40, 0x4C, 0x28, 0x78, 0x80, 0x1E, 0x04, 0x28, 0x10, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x30, 0x1F, + 0x02, 0x3E, 0x00, 0xF0, 0x45, 0xF8, 0x01, 0x28, 0x07, 0xD0, 0x60, 0x68, 0x40, 0x1C, 0x60, 0x60, + 0x00, 0xF0, 0x46, 0xF8, 0x01, 0x28, 0x02, 0xD0, 0x0B, 0xE0, 0x66, 0x60, 0x70, 0xBD, 0x39, 0x48, + 0x61, 0x68, 0x00, 0x68, 0x90, 0xF8, 0x77, 0x00, 0x88, 0x42, 0x02, 0xD2, 0xBD, 0xE8, 0x70, 0x40, + 0xA2, 0xE7, 0x00, 0xF0, 0x47, 0xF8, 0x01, 0x28, 0x0E, 0xD0, 0x70, 0xBD, 0x00, 0xF0, 0x28, 0xF8, + 0x01, 0x28, 0x17, 0xD0, 0x60, 0x68, 0x40, 0x1C, 0x60, 0x60, 0x00, 0xF0, 0x3B, 0xF8, 0x01, 0x28, + 0x02, 0xD0, 0x00, 0xF0, 0x25, 0xF8, 0x0B, 0xE0, 0xBD, 0xE8, 0x70, 0x40, 0x80, 0xE7, 0x00, 0xF0, + 0x17, 0xF8, 0x01, 0x28, 0x06, 0xD0, 0x60, 0x68, 0x40, 0x1C, 0x60, 0x60, 0x00, 0xF0, 0x22, 0xF8, + 0x01, 0x28, 0xE2, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x8A, 0xE7, 0x00, 0xF0, 0x0D, 0xF9, 0x08, 0xB1, + 0x21, 0x78, 0x09, 0xB1, 0x20, 0x70, 0x70, 0xBD, 0x20, 0x70, 0x06, 0x20, 0x28, 0x70, 0x70, 0xBD, + 0x10, 0xB5, 0x00, 0xF0, 0x01, 0xF9, 0x04, 0x46, 0x0B, 0xF0, 0x4F, 0xF8, 0x20, 0x43, 0x10, 0xBD, + 0x18, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x70, 0x00, 0x80, 0x07, 0x01, 0xD5, 0x01, 0x20, 0x70, 0x47, + 0x00, 0x20, 0x70, 0x47, 0x13, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x70, 0x00, 0xC0, 0x07, 0x00, 0xD0, + 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0xFF, 0xF7, 0xF5, 0xFF, 0x01, 0x28, 0x0F, 0xD1, 0x00, 0xF0, + 0x64, 0xF9, 0x60, 0xB9, 0x0B, 0x48, 0x07, 0x49, 0x00, 0x68, 0x49, 0x68, 0x90, 0xF8, 0x78, 0x00, + 0x00, 0xEB, 0x80, 0x00, 0xB1, 0xEB, 0x40, 0x0F, 0x01, 0xD9, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, + 0x10, 0xBD, 0x00, 0x00, 0xD0, 0x04, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, + 0x51, 0x07, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x90, 0x4C, 0x07, 0x46, + 0x0E, 0x46, 0x20, 0x68, 0x00, 0x25, 0x90, 0xF8, 0x98, 0x20, 0x8E, 0x48, 0x0D, 0xF0, 0x07, 0xFF, + 0x02, 0x00, 0x8D, 0x48, 0x29, 0x46, 0x34, 0xD0, 0x02, 0x78, 0x01, 0x25, 0x52, 0x1C, 0xD2, 0xB2, + 0x02, 0x70, 0x23, 0x68, 0x93, 0xF8, 0x99, 0x30, 0x93, 0x42, 0x2B, 0xD2, 0x01, 0x70, 0x85, 0x48, + 0x76, 0x00, 0x32, 0x46, 0x39, 0x46, 0x54, 0x38, 0x12, 0xF0, 0x5C, 0xFB, 0x81, 0x48, 0x32, 0x46, + 0x39, 0x46, 0x2A, 0x38, 0x12, 0xF0, 0x56, 0xFB, 0x20, 0x68, 0x03, 0x26, 0x90, 0xF8, 0x50, 0x12, + 0xC9, 0x07, 0x03, 0xD1, 0x90, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x0B, 0x26, 0xFC, 0xF7, + 0x3D, 0xF9, 0x7A, 0x48, 0x01, 0x68, 0x31, 0x43, 0x01, 0x60, 0xFC, 0xF7, 0x35, 0xF9, 0x20, 0x21, + 0x05, 0x20, 0x0C, 0xF0, 0xB7, 0xFB, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x10, 0xF0, 0xAB, 0xFA, + 0x00, 0xE0, 0x01, 0x70, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x5F, 0x8A, 0x46, + 0x00, 0x28, 0x6E, 0xD0, 0x6C, 0x4D, 0x00, 0x21, 0xDF, 0xF8, 0xB4, 0xB1, 0xE9, 0x70, 0x89, 0x46, + 0x9B, 0xF8, 0x00, 0x20, 0x0C, 0x46, 0x02, 0x2A, 0x03, 0xD0, 0x03, 0x2A, 0x01, 0xD0, 0x05, 0x2A, + 0x5E, 0xD1, 0x00, 0x21, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xD0, 0x01, 0x21, 0xAA, 0x88, 0x00, 0xEB, + 0x41, 0x00, 0x52, 0x1A, 0x16, 0xB2, 0x80, 0x46, 0xAA, 0x78, 0x31, 0x46, 0x00, 0xF0, 0x72, 0xF8, + 0x5B, 0x4F, 0xA8, 0x70, 0x38, 0x68, 0x90, 0xF8, 0x90, 0x00, 0x80, 0x07, 0x04, 0xD5, 0x40, 0x46, + 0x31, 0x46, 0xFF, 0xF7, 0x89, 0xFF, 0x81, 0x46, 0x01, 0x20, 0xDF, 0xF8, 0x58, 0x81, 0xBA, 0xF1, + 0x00, 0x0F, 0x17, 0xD0, 0x00, 0x23, 0x19, 0x46, 0x3F, 0x68, 0x0F, 0xE0, 0x38, 0xF9, 0x11, 0x20, + 0x00, 0x2A, 0x00, 0xDA, 0x52, 0x42, 0xB7, 0xF8, 0x92, 0xC0, 0x62, 0x45, 0x04, 0xDD, 0x97, 0xF8, + 0x91, 0x20, 0x5B, 0x1C, 0x9A, 0x42, 0x14, 0xDD, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xED, 0xDB, + 0x21, 0x46, 0x25, 0xE0, 0x00, 0x22, 0x11, 0x46, 0x3B, 0x68, 0x16, 0xE0, 0x38, 0xF9, 0x11, 0x70, + 0xB3, 0xF8, 0x92, 0xC0, 0x67, 0x45, 0x0E, 0xDD, 0x93, 0xF8, 0x91, 0x70, 0x52, 0x1C, 0x97, 0x42, + 0x09, 0xDC, 0x9B, 0xF8, 0x00, 0x20, 0x01, 0x46, 0x02, 0x2A, 0x09, 0xD0, 0x03, 0x2A, 0x07, 0xD0, + 0x05, 0x2A, 0x08, 0xD0, 0x0C, 0xE0, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xE6, 0xDB, 0xDF, 0xE7, + 0x68, 0x70, 0xE8, 0x70, 0x08, 0xE0, 0x68, 0x78, 0x10, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x02, 0xD0, + 0x69, 0x70, 0xBD, 0xE8, 0xF0, 0x9F, 0x69, 0x70, 0x00, 0xF0, 0x49, 0xF9, 0xBD, 0xE8, 0xF0, 0x5F, + 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x27, 0xBA, 0x2F, 0x48, 0x40, 0x78, 0x70, 0x47, 0x2E, 0x48, + 0x00, 0x21, 0x01, 0x22, 0x01, 0x70, 0x82, 0x70, 0x29, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x31, 0x20, + 0x82, 0x80, 0x2B, 0x4A, 0x12, 0x78, 0x05, 0x2A, 0x02, 0xD0, 0x06, 0x2A, 0x00, 0xD0, 0x41, 0x70, + 0x70, 0x47, 0xEC, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x80, 0x46, 0x23, 0x48, 0x14, 0x46, 0x0D, 0x46, + 0x40, 0x78, 0x16, 0x46, 0x40, 0xB9, 0x1F, 0x48, 0x0A, 0x46, 0x7F, 0x23, 0x41, 0x46, 0x54, 0x38, + 0x00, 0x94, 0x0D, 0xF0, 0x79, 0xFE, 0x00, 0x26, 0x19, 0x4F, 0x38, 0x68, 0x90, 0xF8, 0x90, 0x10, + 0xC9, 0x07, 0x00, 0xD0, 0xEC, 0xB1, 0x17, 0x48, 0x6A, 0x00, 0x41, 0x46, 0x2A, 0x38, 0x12, 0xF0, + 0x81, 0xFA, 0x14, 0x4A, 0x2B, 0x46, 0x54, 0x3A, 0x02, 0xF1, 0x2A, 0x01, 0x11, 0x48, 0x0D, 0xF0, + 0x2C, 0xFE, 0x38, 0x68, 0x90, 0xF8, 0x90, 0x10, 0x49, 0x07, 0x07, 0xD5, 0x90, 0xF8, 0x9A, 0x30, + 0x23, 0xB1, 0x0C, 0x49, 0x2A, 0x46, 0x08, 0x46, 0x0D, 0xF0, 0x6F, 0xFE, 0x30, 0x46, 0xBD, 0xE8, + 0xFC, 0x81, 0xB0, 0xF9, 0x96, 0x10, 0xCD, 0xE9, 0x00, 0x15, 0x06, 0x4A, 0xB0, 0xF9, 0x94, 0x30, + 0x54, 0x3A, 0x41, 0x46, 0x02, 0xF1, 0x2A, 0x00, 0x0D, 0xF0, 0x96, 0xFD, 0xD9, 0xE7, 0x00, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x5A, 0x09, 0x01, 0x20, 0xD8, 0x04, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, + 0xE8, 0x04, 0x10, 0x00, 0x70, 0xB5, 0x00, 0x28, 0x04, 0x9E, 0x0D, 0xD0, 0x00, 0x24, 0x06, 0xE0, + 0x30, 0xF9, 0x11, 0x50, 0x9D, 0x42, 0x01, 0xDD, 0x95, 0x42, 0x00, 0xDB, 0x64, 0x1C, 0x49, 0x1E, + 0xF6, 0xD2, 0xB4, 0x42, 0x01, 0xDD, 0x01, 0x20, 0x70, 0xBD, 0x00, 0x20, 0x70, 0xBD, 0x3F, 0x48, + 0x00, 0x21, 0x01, 0x70, 0x41, 0x60, 0x70, 0x47, 0xF9, 0xE7, 0x3C, 0x48, 0x00, 0x78, 0x70, 0x47, + 0x2D, 0xE9, 0xF3, 0x4F, 0xDF, 0xF8, 0xE8, 0xA0, 0x84, 0x46, 0x4F, 0xF0, 0x00, 0x08, 0xDA, 0xF8, + 0x00, 0x00, 0xDF, 0xF8, 0xD8, 0xB0, 0x81, 0xB0, 0x90, 0xF8, 0x80, 0x10, 0x47, 0x46, 0xC9, 0x07, + 0xC1, 0x46, 0x2B, 0xD0, 0x33, 0x49, 0x09, 0x78, 0x03, 0x29, 0x2D, 0xD0, 0x04, 0x29, 0x2B, 0xD0, + 0x05, 0x29, 0x36, 0xD1, 0xB0, 0xF8, 0x88, 0x60, 0xB0, 0xF8, 0x8A, 0x50, 0x90, 0xF8, 0x87, 0x40, + 0xBC, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x00, 0x94, 0x90, 0xF8, 0x31, 0x10, 0x2B, 0xB2, 0x32, 0xB2, + 0x60, 0x46, 0xFF, 0xF7, 0xB7, 0xFF, 0x80, 0x46, 0x02, 0x98, 0x50, 0xB1, 0x00, 0x94, 0xDA, 0xF8, + 0x00, 0x00, 0x2B, 0xB2, 0x32, 0xB2, 0x90, 0xF8, 0x30, 0x10, 0x02, 0x98, 0xFF, 0xF7, 0xAA, 0xFF, + 0x07, 0x46, 0xB8, 0xF1, 0x01, 0x0F, 0x0E, 0xD0, 0x01, 0x2F, 0x0C, 0xD0, 0x9B, 0xF8, 0x00, 0x10, + 0x58, 0x46, 0x01, 0x29, 0x1D, 0xD0, 0x0A, 0xE0, 0xB0, 0xF8, 0x82, 0x60, 0xB0, 0xF8, 0x84, 0x50, + 0x90, 0xF8, 0x86, 0x40, 0xD4, 0xE7, 0x9B, 0xF8, 0x00, 0x10, 0x58, 0x46, 0x19, 0xB1, 0xCB, 0xF8, + 0x04, 0x90, 0xBD, 0xE8, 0xFE, 0x8F, 0x41, 0x68, 0x49, 0x1C, 0x41, 0x60, 0xDA, 0xF8, 0x00, 0x20, + 0x92, 0xF8, 0x81, 0x20, 0x8A, 0x42, 0xF4, 0xDA, 0x01, 0x21, 0x01, 0x70, 0xCB, 0xF8, 0x04, 0x90, + 0x0D, 0xE0, 0x41, 0x68, 0x49, 0x1C, 0x41, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0x92, 0xF8, 0x81, 0x20, + 0x8A, 0x42, 0xE6, 0xDA, 0x80, 0xF8, 0x00, 0x90, 0x00, 0x21, 0xCB, 0xF8, 0x04, 0x90, 0x03, 0xB0, + 0x07, 0x20, 0xBD, 0xE8, 0xF0, 0x4F, 0x0C, 0xF0, 0x35, 0xBA, 0x00, 0x00, 0xE0, 0x04, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x22, 0x48, 0x08, 0xB5, 0x00, 0x21, 0x41, 0x60, + 0x01, 0x22, 0x81, 0x60, 0x02, 0x70, 0x41, 0x70, 0x1F, 0x48, 0x01, 0x70, 0xFF, 0xF7, 0x09, 0xFF, + 0xFF, 0xF7, 0x72, 0xFF, 0xFF, 0xF7, 0xFB, 0xFB, 0xFF, 0xF7, 0x7F, 0xFD, 0x6B, 0x46, 0x00, 0x22, + 0x5E, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x58, 0xF9, 0x00, 0x98, 0x41, 0x07, 0x03, 0xD5, 0xFF, 0xF7, + 0xF4, 0xFA, 0x04, 0x21, 0x0E, 0xE0, 0x01, 0x07, 0x03, 0xD5, 0xFF, 0xF7, 0x19, 0xF9, 0x08, 0x21, + 0x08, 0xE0, 0xC1, 0x06, 0x03, 0xD5, 0xFF, 0xF7, 0x7D, 0xFA, 0x10, 0x21, 0x02, 0xE0, 0x41, 0x06, + 0x04, 0xD5, 0x40, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x22, 0xF9, 0xDF, 0xE7, 0x80, 0x07, 0xDD, 0xD5, + 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x1B, 0xF9, 0xFF, 0xF7, 0xD5, 0xFB, 0xD6, 0xE7, 0x00, 0xEB, + 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x11, 0xF0, 0x85, 0xBE, 0x11, 0xF0, + 0xA5, 0xBE, 0x00, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x52, 0x07, 0x10, 0x00, 0x00, 0xF0, 0xA3, 0xBF, + 0x5E, 0x48, 0x40, 0x78, 0x00, 0x28, 0x0B, 0xD0, 0x5D, 0x48, 0x5E, 0x49, 0x00, 0x7E, 0x09, 0x7E, + 0xC8, 0x42, 0x05, 0xD1, 0x01, 0x23, 0x5C, 0x4A, 0x5A, 0x49, 0x59, 0x48, 0x00, 0xF0, 0xE0, 0xBB, + 0x70, 0x47, 0x3C, 0xB5, 0x00, 0x23, 0x00, 0x93, 0x01, 0x93, 0x6B, 0x46, 0x07, 0xE0, 0x44, 0x18, + 0x64, 0x78, 0x14, 0xB1, 0x1D, 0x5D, 0x6D, 0x1C, 0x1D, 0x55, 0x49, 0x1C, 0xC9, 0xB2, 0x91, 0x42, + 0xF5, 0xD9, 0x00, 0x20, 0x01, 0x21, 0x1C, 0x5C, 0x5A, 0x5C, 0xA2, 0x42, 0x00, 0xD9, 0x08, 0x46, + 0x49, 0x1C, 0xC9, 0xB2, 0x06, 0x29, 0xF6, 0xD3, 0x3C, 0xBD, 0x70, 0xB5, 0x04, 0x46, 0x00, 0x20, + 0x08, 0x70, 0x0E, 0x46, 0x10, 0x70, 0x46, 0x48, 0x46, 0x49, 0x15, 0x46, 0x00, 0x7E, 0x09, 0x7E, + 0xC8, 0x42, 0x0B, 0xD0, 0xE2, 0x78, 0xA1, 0x78, 0x44, 0x48, 0xFF, 0xF7, 0xD2, 0xFF, 0x30, 0x70, + 0x62, 0x78, 0x21, 0x78, 0x42, 0x48, 0xFF, 0xF7, 0xCC, 0xFF, 0x28, 0x70, 0x70, 0xBD, 0x70, 0xB5, + 0x00, 0x24, 0x01, 0x23, 0x05, 0x7E, 0x08, 0xE0, 0xC6, 0x18, 0x96, 0xF9, 0x12, 0x60, 0x8E, 0x42, + 0x02, 0xDB, 0x96, 0x42, 0x00, 0xDC, 0x64, 0x1C, 0x5B, 0x1C, 0x9D, 0x42, 0xF4, 0xD2, 0x01, 0x2C, + 0x01, 0xDC, 0x01, 0x20, 0x70, 0xBD, 0x00, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x43, 0x99, 0x46, + 0x00, 0x23, 0x1F, 0x46, 0x47, 0xF6, 0xFF, 0x76, 0x4F, 0xF0, 0xFF, 0x3C, 0x01, 0x25, 0x04, 0x7E, + 0x0D, 0xE0, 0x00, 0xBF, 0x00, 0xEB, 0x05, 0x08, 0x98, 0xF9, 0x12, 0x80, 0x88, 0x45, 0x05, 0xDB, + 0x90, 0x45, 0x03, 0xDC, 0x43, 0x19, 0x93, 0xF9, 0x12, 0x30, 0x02, 0xE0, 0x6D, 0x1C, 0xAC, 0x42, + 0xF0, 0xD2, 0x64, 0x1C, 0x0A, 0xE0, 0x05, 0x19, 0x95, 0xF9, 0x12, 0x50, 0x8D, 0x42, 0x05, 0xDB, + 0x95, 0x42, 0x03, 0xDC, 0x20, 0x44, 0x90, 0xF9, 0x12, 0x70, 0x01, 0xE0, 0x64, 0x1E, 0xF2, 0xD1, + 0xBB, 0x42, 0x09, 0xD1, 0x0A, 0xE0, 0x00, 0xBF, 0x39, 0xF9, 0x13, 0x00, 0xB0, 0x42, 0x02, 0xDA, + 0x06, 0x46, 0x4F, 0xFA, 0x83, 0xFC, 0x5B, 0x1C, 0xBB, 0x42, 0xF5, 0xDD, 0x60, 0x46, 0xBD, 0xE8, + 0xF0, 0x83, 0x2D, 0xE9, 0xF0, 0x41, 0x17, 0x46, 0x0E, 0x46, 0x04, 0x46, 0xC2, 0x78, 0x81, 0x78, + 0x0F, 0x48, 0xFF, 0xF7, 0xA4, 0xFF, 0x05, 0x00, 0x06, 0xD1, 0xE2, 0x78, 0xA1, 0x78, 0x11, 0x4B, + 0x0B, 0x48, 0xFF, 0xF7, 0xB2, 0xFF, 0x30, 0x70, 0x62, 0x78, 0x21, 0x78, 0x09, 0x48, 0xFF, 0xF7, + 0x96, 0xFF, 0x06, 0x00, 0x06, 0xD1, 0x62, 0x78, 0x21, 0x78, 0x0B, 0x4B, 0x05, 0x48, 0xFF, 0xF7, + 0xA4, 0xFF, 0x38, 0x70, 0x05, 0xEA, 0x06, 0x00, 0xBD, 0xE8, 0xF0, 0x81, 0xEC, 0x06, 0x10, 0x00, + 0x58, 0x23, 0x10, 0x00, 0x98, 0x23, 0x10, 0x00, 0x80, 0x24, 0x10, 0x00, 0xFC, 0x0B, 0x01, 0x20, + 0x13, 0x0C, 0x01, 0x20, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, 0x2D, 0xE9, 0xF0, 0x47, + 0x00, 0x25, 0x82, 0x46, 0xA6, 0xB0, 0x50, 0x1E, 0xC7, 0xB2, 0x2C, 0x46, 0x28, 0x46, 0x6B, 0x46, + 0x0D, 0xF1, 0x4C, 0x09, 0x12, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x10, 0x60, 0x35, 0x44, 0x46, 0x1C, + 0xB4, 0x46, 0x95, 0xFB, 0xF6, 0xF6, 0x23, 0xF8, 0x10, 0x60, 0x3E, 0x1A, 0x40, 0x1C, 0x31, 0xF9, + 0x16, 0x80, 0x44, 0x44, 0x94, 0xFB, 0xFC, 0xFC, 0x29, 0xF8, 0x16, 0xC0, 0x90, 0x42, 0xEB, 0xDB, + 0x48, 0x46, 0x0C, 0xE0, 0x33, 0xF9, 0x12, 0x40, 0x30, 0xF9, 0x12, 0x50, 0x2C, 0x44, 0x31, 0xF8, + 0x12, 0x50, 0x04, 0xEB, 0xD4, 0x74, 0xA5, 0xEB, 0x64, 0x04, 0x2A, 0xF8, 0x12, 0x40, 0x52, 0x1E, + 0xF0, 0xD2, 0x26, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x4F, 0x4F, 0xF0, 0x00, 0x0B, + 0xA7, 0xB0, 0xC0, 0xF8, 0x00, 0xB0, 0x81, 0x46, 0xC0, 0xF8, 0x04, 0xB0, 0x98, 0x46, 0x14, 0x46, + 0x5D, 0x46, 0x5E, 0x46, 0xDA, 0x46, 0x5F, 0x46, 0x28, 0x21, 0x01, 0xA8, 0x12, 0xF0, 0xF3, 0xF8, + 0x4C, 0x21, 0x0B, 0xA8, 0x12, 0xF0, 0xEF, 0xF8, 0xCD, 0xF8, 0x00, 0x80, 0x02, 0x23, 0x22, 0x46, + 0x0B, 0xA8, 0x28, 0x99, 0x0D, 0xF0, 0x16, 0xFC, 0x8E, 0x49, 0x01, 0x20, 0x02, 0x46, 0x00, 0x23, + 0x0D, 0xF1, 0x04, 0x0E, 0xD1, 0xF8, 0x00, 0x80, 0x17, 0xE0, 0x0B, 0xA9, 0x31, 0xF9, 0x10, 0xC0, + 0xB8, 0xF9, 0x4E, 0x12, 0x8C, 0x45, 0x04, 0xDD, 0x4F, 0xF0, 0x01, 0x0B, 0x0E, 0xF8, 0x00, 0x20, + 0x0A, 0xE0, 0x49, 0x42, 0x8C, 0x45, 0x05, 0xDA, 0xFF, 0x21, 0x4F, 0xF0, 0x01, 0x0B, 0x0E, 0xF8, + 0x00, 0x10, 0x01, 0xE0, 0x0E, 0xF8, 0x00, 0x30, 0x40, 0x1C, 0xA0, 0x42, 0xE5, 0xDB, 0xBB, 0xF1, + 0x01, 0x0F, 0x42, 0xD1, 0x01, 0x20, 0x71, 0x46, 0x09, 0xE0, 0x0A, 0x5C, 0x32, 0xB1, 0xC5, 0xB2, + 0x08, 0x56, 0x00, 0x28, 0x05, 0xDD, 0x4F, 0xF0, 0x01, 0x0A, 0x02, 0xE0, 0x40, 0x1C, 0xA0, 0x42, + 0xF3, 0xDB, 0x60, 0x1E, 0x07, 0xE0, 0x0A, 0x5C, 0x2A, 0xB1, 0xC6, 0xB2, 0x08, 0x56, 0x00, 0x28, + 0x03, 0xDA, 0x01, 0x27, 0x01, 0xE0, 0x40, 0x1E, 0xF5, 0xD2, 0xA4, 0xF1, 0x01, 0x08, 0xBA, 0xF1, + 0x00, 0x0F, 0x01, 0xD0, 0x97, 0xB9, 0x02, 0xE0, 0x4F, 0xF0, 0x01, 0x05, 0x77, 0xB9, 0x08, 0xF0, + 0xFF, 0x06, 0x0B, 0xE0, 0xD9, 0xE9, 0x00, 0x47, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, + 0xBA, 0xFF, 0x04, 0x43, 0x0F, 0x43, 0xC9, 0xE9, 0x00, 0x47, 0x6D, 0x1C, 0xB5, 0x42, 0xF1, 0xDD, + 0xD9, 0xE9, 0x00, 0x04, 0x40, 0xF0, 0x01, 0x05, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, + 0xAA, 0xFF, 0x05, 0x43, 0x0C, 0x43, 0xC9, 0xE9, 0x00, 0x54, 0x2B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0x16, 0x46, 0x0F, 0x46, 0x03, 0x20, 0x0F, 0xF0, 0xE3, 0xFF, + 0x55, 0x4C, 0x56, 0x4A, 0x29, 0x46, 0x23, 0x78, 0x55, 0x48, 0x0D, 0xF0, 0x7E, 0xFB, 0x55, 0x4D, + 0x53, 0x48, 0x55, 0x4A, 0x2B, 0x78, 0x39, 0x46, 0x2A, 0x30, 0x0D, 0xF0, 0x76, 0xFB, 0x03, 0x20, + 0x0F, 0xF0, 0xEC, 0xFF, 0xDF, 0xF8, 0x2C, 0x81, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE0, 0x13, + 0x89, 0x07, 0x12, 0xD5, 0x90, 0xF8, 0xF4, 0x03, 0x00, 0x96, 0x00, 0xF0, 0x0F, 0x07, 0x3B, 0x46, + 0x22, 0x78, 0x47, 0x49, 0x49, 0x48, 0x0D, 0xF0, 0x7D, 0xFB, 0x45, 0x49, 0x00, 0x96, 0x3B, 0x46, + 0x2A, 0x78, 0x2A, 0x31, 0x46, 0x48, 0x0D, 0xF0, 0x75, 0xFB, 0x22, 0x78, 0x40, 0x49, 0x45, 0x48, + 0x00, 0xF0, 0x5B, 0xF8, 0x3E, 0x49, 0x2A, 0x78, 0x2A, 0x31, 0x43, 0x48, 0x00, 0xF0, 0x55, 0xF8, + 0x42, 0x4F, 0x00, 0x96, 0x22, 0x78, 0x3F, 0x49, 0x41, 0x48, 0x3B, 0x68, 0x0D, 0xF0, 0x62, 0xFB, + 0x00, 0x96, 0x2A, 0x78, 0x3C, 0x49, 0x3F, 0x48, 0x3B, 0x68, 0x0D, 0xF0, 0x5B, 0xFB, 0xD8, 0xF8, + 0x00, 0x00, 0x47, 0x46, 0x90, 0xF8, 0x30, 0x02, 0xC0, 0x06, 0x0A, 0xD5, 0x22, 0x78, 0x38, 0x49, + 0x39, 0x48, 0xFF, 0xF7, 0xE3, 0xFE, 0x2A, 0x78, 0x36, 0x49, 0x38, 0x48, 0xFF, 0xF7, 0xDE, 0xFE, + 0x0B, 0xE0, 0x20, 0x78, 0x32, 0x49, 0x42, 0x00, 0x33, 0x48, 0x11, 0xF0, 0x73, 0xFF, 0x28, 0x78, + 0x30, 0x49, 0x42, 0x00, 0x31, 0x48, 0x11, 0xF0, 0x6D, 0xFF, 0x38, 0x68, 0x90, 0xF8, 0x30, 0x02, + 0x80, 0x06, 0x04, 0xD5, 0x2C, 0x49, 0x22, 0x78, 0x08, 0x46, 0x00, 0xF0, 0x30, 0xF8, 0x38, 0x68, + 0x90, 0xF8, 0x30, 0x02, 0x40, 0x06, 0x04, 0xD5, 0x28, 0x49, 0x2A, 0x78, 0x08, 0x46, 0x00, 0xF0, + 0x26, 0xF8, 0x33, 0x46, 0x22, 0x78, 0x1A, 0x49, 0x25, 0x48, 0xFF, 0xF7, 0xED, 0xFE, 0x2A, 0x78, + 0x01, 0xB0, 0x33, 0x46, 0xBD, 0xE8, 0xF0, 0x43, 0x15, 0x49, 0x21, 0x48, 0x2A, 0x31, 0x08, 0x30, + 0xE2, 0xE6, 0x20, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x30, 0xB5, 0x00, 0x23, 0x03, 0x80, + 0x01, 0x23, 0x09, 0xE0, 0x00, 0xEB, 0x43, 0x04, 0x31, 0xF8, 0x13, 0x50, 0x34, 0xF8, 0x02, 0x4C, + 0x2C, 0x44, 0x20, 0xF8, 0x13, 0x40, 0x5B, 0x1C, 0x93, 0x42, 0xF3, 0xDB, 0x30, 0xBD, 0x08, 0xB5, + 0x00, 0x92, 0x04, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x4C, 0x32, 0xB2, 0xF9, 0x4A, 0x22, 0x01, 0xF0, + 0xED, 0xFC, 0x08, 0xBD, 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, + 0x84, 0x09, 0x01, 0x20, 0xBA, 0x06, 0x10, 0x00, 0x94, 0x4A, 0x01, 0x20, 0x08, 0x24, 0x10, 0x00, + 0x32, 0x24, 0x10, 0x00, 0x92, 0x0A, 0x01, 0x20, 0xAC, 0x0B, 0x01, 0x20, 0x78, 0x06, 0x10, 0x00, + 0xC0, 0x0A, 0x01, 0x20, 0xEA, 0x0A, 0x01, 0x20, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, + 0x90, 0x24, 0x10, 0x00, 0xC0, 0x06, 0x10, 0x00, 0x10, 0xB5, 0x40, 0x21, 0xFA, 0x48, 0x11, 0xF0, + 0xA2, 0xFF, 0xF9, 0x48, 0x40, 0x21, 0x40, 0x30, 0x11, 0xF0, 0x9D, 0xFF, 0xF6, 0x48, 0x00, 0x21, + 0x80, 0x30, 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x10, 0x30, 0xC0, 0xE9, 0x00, 0x11, + 0xC0, 0xE9, 0x02, 0x11, 0x10, 0x30, 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x08, 0x46, + 0xEE, 0x49, 0x08, 0x60, 0x10, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x06, 0x46, 0x89, 0x46, 0xEC, 0x48, + 0xEC, 0x49, 0x98, 0x46, 0x00, 0x78, 0x09, 0x68, 0x14, 0x46, 0x01, 0x28, 0x50, 0xD0, 0xB1, 0xF9, + 0x86, 0xA2, 0x91, 0xF8, 0x88, 0x52, 0xB1, 0xF9, 0x82, 0x72, 0x11, 0x46, 0x48, 0x46, 0x0D, 0xF0, + 0x26, 0xFB, 0x83, 0x46, 0x21, 0x46, 0x48, 0x46, 0x0D, 0xF0, 0x2C, 0xFB, 0x00, 0x90, 0x39, 0x46, + 0x58, 0x46, 0x0C, 0xF0, 0xFB, 0xFB, 0x0F, 0xFA, 0x80, 0xFB, 0x39, 0x46, 0x00, 0x98, 0x0C, 0xF0, + 0xF5, 0xFB, 0x00, 0xB2, 0xAB, 0xEB, 0x00, 0x00, 0x68, 0x43, 0x64, 0x21, 0x90, 0xFB, 0xF1, 0xF0, + 0x38, 0x44, 0x05, 0xB2, 0xA8, 0xF8, 0x08, 0x50, 0x70, 0x1C, 0x00, 0x21, 0x03, 0x90, 0xC8, 0xF8, + 0x00, 0x10, 0xC8, 0xF8, 0x04, 0x10, 0xB9, 0xF9, 0x00, 0x00, 0xA8, 0x42, 0x02, 0xDD, 0x03, 0x99, + 0x01, 0x20, 0x08, 0x70, 0x09, 0xEB, 0x44, 0x00, 0x76, 0x1C, 0x30, 0xF9, 0x02, 0x2C, 0x31, 0x19, + 0xAA, 0x42, 0x02, 0xDD, 0x01, 0x22, 0x01, 0xF8, 0x01, 0x2C, 0xB9, 0xF9, 0x02, 0x30, 0x03, 0xEB, + 0x0A, 0x02, 0x12, 0xB2, 0xAB, 0x42, 0x18, 0xDD, 0xB9, 0xF9, 0x00, 0x30, 0x93, 0x42, 0x03, 0xDD, + 0xB9, 0xF9, 0x04, 0x30, 0x93, 0x42, 0x0A, 0xDC, 0x03, 0x9B, 0x01, 0x22, 0x5A, 0x70, 0x0C, 0xE0, + 0xB1, 0xF9, 0x6A, 0xA2, 0x91, 0xF8, 0x65, 0x52, 0xB1, 0xF9, 0x66, 0x72, 0xAD, 0xE7, 0xD8, 0xF8, + 0x00, 0x60, 0x46, 0xF0, 0x02, 0x06, 0xC8, 0xF8, 0x00, 0x60, 0x30, 0xF9, 0x04, 0x3C, 0xA4, 0xF1, + 0x02, 0x0B, 0x03, 0xEB, 0x0A, 0x02, 0x12, 0xB2, 0xAB, 0x42, 0x16, 0xDD, 0x30, 0xF9, 0x06, 0x3C, + 0x93, 0x42, 0x03, 0xDD, 0x30, 0xF9, 0x02, 0x0C, 0x90, 0x42, 0x03, 0xDC, 0x01, 0x20, 0x01, 0xF8, + 0x02, 0x0C, 0x0A, 0xE0, 0xD8, 0xE9, 0x00, 0x64, 0x5A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, + 0x2A, 0xFE, 0x06, 0x43, 0x0C, 0x43, 0xC8, 0xE9, 0x00, 0x64, 0x02, 0x24, 0x58, 0xE0, 0x00, 0xBF, + 0x39, 0xF9, 0x14, 0x00, 0xA8, 0x42, 0x52, 0xDD, 0x09, 0xEB, 0x44, 0x01, 0x02, 0x91, 0x50, 0x44, + 0x31, 0xF9, 0x02, 0x1C, 0x00, 0xB2, 0x81, 0x42, 0x04, 0xDD, 0x02, 0x9A, 0xB2, 0xF9, 0x02, 0x20, + 0x82, 0x42, 0x10, 0xDC, 0x02, 0x9A, 0x32, 0xF9, 0x04, 0x2C, 0x82, 0x42, 0x04, 0xDD, 0x02, 0x9A, + 0xB2, 0xF9, 0x02, 0x20, 0x82, 0x42, 0x06, 0xDC, 0x81, 0x42, 0x35, 0xDD, 0x02, 0x99, 0xB1, 0xF9, + 0x04, 0x10, 0x81, 0x42, 0x30, 0xDD, 0xD8, 0xE9, 0x00, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x11, 0xF0, 0xF9, 0xFD, 0xCD, 0xE9, 0x00, 0x01, 0x06, 0x43, 0x0F, 0x43, 0x62, 0x1E, 0x01, 0x20, + 0x00, 0x21, 0xC8, 0xE9, 0x00, 0x67, 0x11, 0xF0, 0xEE, 0xFD, 0x02, 0x46, 0x0B, 0x46, 0x06, 0xEA, + 0x02, 0x00, 0x07, 0xEA, 0x03, 0x01, 0x08, 0x43, 0x19, 0xD0, 0x02, 0x98, 0x39, 0xF9, 0x14, 0x10, + 0x30, 0xF9, 0x02, 0x0C, 0x81, 0x42, 0x09, 0xDA, 0x96, 0x43, 0x9F, 0x43, 0xC8, 0xE9, 0x00, 0x67, + 0x03, 0x99, 0x01, 0x20, 0x21, 0x44, 0x01, 0xF8, 0x01, 0x0C, 0x08, 0xE0, 0xDD, 0xE9, 0x00, 0x10, + 0x8E, 0x43, 0x87, 0x43, 0xC8, 0xE9, 0x00, 0x67, 0x03, 0x99, 0x01, 0x20, 0x08, 0x55, 0x64, 0x1C, + 0x5C, 0x45, 0xA5, 0xD3, 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0x82, 0x46, + 0x00, 0x21, 0x1D, 0x46, 0x19, 0x76, 0x06, 0x20, 0x90, 0x46, 0xC3, 0x1F, 0x76, 0x4C, 0x07, 0xE0, + 0x00, 0x22, 0x29, 0x18, 0x0A, 0x73, 0x8B, 0x74, 0x05, 0xEB, 0x40, 0x01, 0x22, 0x88, 0x0A, 0x80, + 0x40, 0x1E, 0xF5, 0xD2, 0x6E, 0x48, 0x01, 0x78, 0x6E, 0x48, 0x01, 0x29, 0x00, 0x68, 0x06, 0xD0, + 0xB0, 0xF9, 0x84, 0x22, 0x4F, 0xF0, 0x00, 0x0B, 0x59, 0x46, 0x58, 0x46, 0x16, 0xE0, 0xB0, 0xF9, + 0x68, 0x22, 0xF7, 0xE7, 0x0A, 0xEB, 0x00, 0x03, 0x5C, 0x78, 0x74, 0xB1, 0x1A, 0xF8, 0x00, 0x40, + 0x0C, 0xB9, 0x49, 0x1C, 0xC9, 0xB2, 0x59, 0x70, 0x02, 0x9B, 0x33, 0xF9, 0x10, 0x30, 0x93, 0x42, + 0x03, 0xDD, 0x01, 0x23, 0x8B, 0x40, 0x43, 0xEA, 0x0B, 0x0B, 0x40, 0x1C, 0x40, 0x45, 0xE9, 0xD3, + 0x5E, 0x48, 0x00, 0x90, 0x0E, 0x98, 0x4F, 0xF0, 0x00, 0x09, 0x4C, 0x46, 0xC0, 0xE9, 0x00, 0x99, + 0x37, 0xE0, 0x00, 0xBF, 0x0A, 0xEB, 0x04, 0x00, 0x42, 0x78, 0x8A, 0xB3, 0x01, 0x21, 0x91, 0x40, + 0x11, 0xEA, 0x0B, 0x0F, 0x02, 0xD1, 0x00, 0x21, 0x41, 0x70, 0x29, 0xE0, 0x1A, 0xF8, 0x04, 0x10, + 0x39, 0xB9, 0x09, 0xF1, 0x01, 0x01, 0x01, 0xF0, 0xFF, 0x09, 0x50, 0x49, 0x00, 0x91, 0x05, 0xF8, + 0x19, 0x40, 0x80, 0xF8, 0x01, 0x90, 0x0E, 0x98, 0x22, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67, + 0x01, 0x20, 0x11, 0xF0, 0x60, 0xFD, 0x06, 0x43, 0x0E, 0x98, 0x0F, 0x43, 0xC0, 0xE9, 0x00, 0x67, + 0x05, 0xEB, 0x09, 0x00, 0x01, 0x7B, 0x49, 0x1C, 0x01, 0x73, 0x05, 0xEB, 0x49, 0x01, 0x4C, 0x70, + 0x02, 0x99, 0x00, 0x9A, 0x31, 0xF9, 0x14, 0x10, 0x91, 0x42, 0x01, 0xDD, 0x00, 0x91, 0x84, 0x74, + 0x64, 0x1C, 0x44, 0x45, 0xC6, 0xD3, 0x85, 0xF8, 0x18, 0x90, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x2D, 0xE9, 0xF8, 0x4F, 0x0C, 0x46, 0x05, 0x46, 0x1E, 0x46, 0x91, 0x46, 0x17, 0x21, 0x38, 0x48, + 0x11, 0xF0, 0xEF, 0xFD, 0x28, 0x21, 0x37, 0x48, 0x11, 0xF0, 0xEB, 0xFD, 0xDF, 0xF8, 0xD8, 0xA0, + 0x36, 0x4F, 0x09, 0xF1, 0x08, 0x08, 0x9A, 0xF8, 0x00, 0x10, 0x76, 0xB1, 0x0A, 0x46, 0x05, 0xF1, + 0x20, 0x03, 0x33, 0x49, 0x2E, 0x48, 0xFF, 0xF7, 0x76, 0xFE, 0x04, 0xF1, 0x20, 0x03, 0x3A, 0x78, + 0x30, 0x49, 0x2C, 0x48, 0xFF, 0xF7, 0x6F, 0xFE, 0x11, 0xE0, 0x4A, 0x46, 0x28, 0x48, 0x00, 0xF0, + 0x24, 0xF9, 0x42, 0x46, 0x39, 0x78, 0x27, 0x48, 0x00, 0xF0, 0x1F, 0xF9, 0x00, 0x20, 0xC5, 0xE9, + 0x08, 0x00, 0xC4, 0xE9, 0x08, 0x00, 0x28, 0x48, 0x00, 0x88, 0x28, 0x85, 0x20, 0x85, 0x27, 0x4E, + 0x28, 0x8D, 0x2B, 0x46, 0x26, 0xF8, 0x11, 0x0F, 0x20, 0x8D, 0x70, 0x80, 0xCD, 0xF8, 0x00, 0x90, + 0x9A, 0xF8, 0x00, 0x20, 0x1E, 0x49, 0x1A, 0x48, 0xFF, 0xF7, 0x36, 0xFF, 0xCD, 0xF8, 0x00, 0x80, + 0x23, 0x46, 0x3A, 0x78, 0x1B, 0x49, 0x17, 0x48, 0xFF, 0xF7, 0x2E, 0xFF, 0x29, 0x7E, 0x30, 0x79, + 0x61, 0xF3, 0x03, 0x00, 0x30, 0x71, 0x21, 0x7E, 0x61, 0xF3, 0x07, 0x10, 0x30, 0x71, 0xBD, 0xE8, + 0xF8, 0x8F, 0x70, 0xB5, 0x0B, 0x4C, 0x20, 0x68, 0x90, 0xF8, 0x30, 0x12, 0x09, 0x07, 0x42, 0xD5, + 0x13, 0x49, 0x0A, 0x78, 0x0A, 0xB9, 0x49, 0x78, 0xE9, 0xB3, 0x05, 0x49, 0x09, 0x78, 0x01, 0x29, + 0x20, 0xD0, 0xB0, 0xF8, 0x42, 0x12, 0x1F, 0xE0, 0x58, 0x23, 0x10, 0x00, 0x00, 0x05, 0x10, 0x00, + 0x0E, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x18, 0x6B, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0xFC, 0x0B, 0x01, 0x20, 0x13, 0x0C, 0x01, 0x20, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, + 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, 0x10, 0x05, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, + 0xEC, 0x06, 0x10, 0x00, 0xB0, 0xF8, 0x48, 0x12, 0x01, 0x22, 0x0D, 0xB2, 0xB0, 0xF9, 0x44, 0x12, + 0x6A, 0x48, 0x00, 0xF0, 0x94, 0xFA, 0x20, 0x68, 0x01, 0x22, 0xB0, 0xF9, 0x46, 0x12, 0x67, 0x48, + 0x10, 0x30, 0x00, 0xF0, 0x8C, 0xFA, 0x29, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x63, 0x48, 0x01, 0x22, + 0x10, 0x38, 0x00, 0xF0, 0x84, 0xBA, 0x61, 0x48, 0x4F, 0xF0, 0xFF, 0x31, 0xC0, 0xE9, 0x00, 0x11, + 0xC0, 0xE9, 0x02, 0x11, 0x10, 0x38, 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x20, 0x30, + 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x70, 0xBD, 0x2D, 0xE9, 0xFF, 0x4F, 0x83, 0xB0, + 0x15, 0x46, 0x06, 0x99, 0x91, 0xF8, 0x40, 0x10, 0x02, 0x29, 0x0C, 0xD0, 0x01, 0x29, 0x0C, 0xD0, + 0x52, 0x49, 0x10, 0x39, 0x8A, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0xA9, 0x78, 0x11, 0xF0, 0x48, 0xFE, + 0x81, 0x46, 0xA8, 0x78, 0x32, 0xE0, 0x4D, 0x49, 0xF4, 0xE7, 0x4C, 0x49, 0x10, 0x31, 0xF1, 0xE7, + 0x02, 0x46, 0x2C, 0x78, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x6D, 0xFC, 0xCD, 0xE9, 0x00, 0x01, + 0x1D, 0xE0, 0x00, 0xBF, 0x19, 0xF8, 0x04, 0x10, 0x04, 0x98, 0x81, 0x42, 0x16, 0xD1, 0xDD, 0xE9, + 0x00, 0x23, 0xDA, 0xE9, 0x00, 0x01, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x23, 0xD0, 0xDA, 0xE9, + 0x02, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x55, 0xFC, 0x06, 0x40, 0x0F, 0x40, + 0x3E, 0x43, 0x18, 0xD0, 0x0B, 0xF1, 0x01, 0x00, 0x1F, 0xFA, 0x80, 0xFB, 0x64, 0x1C, 0x68, 0x78, + 0xA0, 0x42, 0xDF, 0xDA, 0x09, 0xF1, 0x28, 0x09, 0x08, 0xF1, 0x01, 0x00, 0xE9, 0x78, 0x80, 0x46, + 0x41, 0x45, 0xCD, 0xDA, 0x06, 0x99, 0x5F, 0xEA, 0x0B, 0x00, 0xA1, 0xF8, 0x26, 0xB0, 0x00, 0xD0, + 0x01, 0x20, 0x07, 0xB0, 0xF2, 0xE6, 0x00, 0x20, 0x09, 0xF8, 0x04, 0x00, 0xE6, 0xE7, 0x2D, 0xE9, + 0xFC, 0x5F, 0x80, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0x87, 0x78, 0x90, 0xF8, 0x03, 0xA0, 0x2A, 0xE0, + 0x98, 0xF8, 0x00, 0x40, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x24, 0xFC, 0x24, 0x4E, + 0xD6, 0xE9, 0x00, 0x32, 0x03, 0x40, 0x0A, 0x40, 0xCD, 0xE9, 0x00, 0x23, 0xD6, 0xE9, 0x02, 0x56, + 0x98, 0xF8, 0x01, 0x90, 0x14, 0xE0, 0x00, 0xBF, 0xDD, 0xE9, 0x00, 0x10, 0x08, 0x43, 0x0E, 0xD0, + 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x0E, 0xFC, 0x05, 0xEA, 0x00, 0x02, 0x06, 0xEA, + 0x01, 0x00, 0x02, 0x43, 0x03, 0xD0, 0x0B, 0xF1, 0x01, 0x00, 0x1F, 0xFA, 0x80, 0xFB, 0x64, 0x1C, + 0xA1, 0x45, 0xE9, 0xDA, 0x7F, 0x1C, 0xBA, 0x45, 0xD2, 0xDA, 0xBB, 0xF1, 0x00, 0x0F, 0x02, 0xD0, + 0x01, 0x20, 0xBD, 0xE8, 0xFC, 0x9F, 0x00, 0x20, 0xFB, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0x91, 0x46, + 0x45, 0x1C, 0x0C, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x0C, 0xE0, 0xD9, 0xE9, 0x00, 0x67, 0x22, 0x46, + 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0xE7, 0xFB, 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x01, 0xD0, + 0x05, 0xF8, 0x04, 0x80, 0x64, 0x1E, 0xF0, 0xD2, 0xBD, 0xE8, 0xF0, 0x87, 0xE8, 0x23, 0x10, 0x00, + 0x90, 0x24, 0x10, 0x00, 0xA1, 0x4A, 0x10, 0xB5, 0x13, 0x68, 0x00, 0x21, 0xB3, 0xF8, 0x14, 0x22, + 0x82, 0x42, 0x05, 0xDA, 0x93, 0xF8, 0x10, 0x22, 0x52, 0x07, 0x01, 0xD5, 0x02, 0x21, 0x08, 0xE0, + 0xB3, 0xF8, 0x12, 0x22, 0x82, 0x42, 0x04, 0xDA, 0x93, 0xF8, 0x10, 0x02, 0x80, 0x07, 0x00, 0xD5, + 0x01, 0x21, 0x97, 0x48, 0x97, 0x4C, 0x42, 0x78, 0x91, 0x42, 0x14, 0xD1, 0xA1, 0x78, 0x91, 0x42, + 0x0D, 0xD0, 0x95, 0x4B, 0x1B, 0x78, 0x1A, 0x43, 0x94, 0x4B, 0x1B, 0x78, 0x1A, 0x43, 0x07, 0xD0, + 0x41, 0x68, 0x49, 0x1E, 0x41, 0x60, 0x00, 0x29, 0x01, 0xDC, 0x40, 0x78, 0xA0, 0x70, 0x10, 0xBD, + 0x41, 0x70, 0x41, 0x68, 0xF7, 0xE7, 0x59, 0xB1, 0x02, 0x29, 0x01, 0xD1, 0x01, 0x2A, 0x07, 0xD0, + 0x93, 0xF8, 0x18, 0x22, 0x42, 0x60, 0x41, 0x70, 0x00, 0x2A, 0xF0, 0xDC, 0xA1, 0x70, 0x10, 0xBD, + 0x93, 0xF8, 0x19, 0x22, 0xF6, 0xE7, 0x70, 0xB5, 0x85, 0x4A, 0x86, 0x4B, 0x81, 0x4D, 0x16, 0x78, + 0x7E, 0x4A, 0x9C, 0x79, 0x00, 0x21, 0x12, 0x68, 0xAB, 0x78, 0x01, 0x2E, 0x02, 0xD1, 0x82, 0x4E, + 0x36, 0x78, 0x4E, 0xB1, 0xB2, 0xF8, 0x14, 0x62, 0x86, 0x42, 0x17, 0xDA, 0x92, 0xF8, 0x10, 0x62, + 0x76, 0x07, 0x13, 0xD5, 0x02, 0x21, 0x25, 0xE0, 0xB2, 0xF8, 0x1C, 0x62, 0x86, 0x42, 0x03, 0xDA, + 0x92, 0xF8, 0x10, 0x62, 0x76, 0x07, 0xF5, 0xD4, 0xB2, 0xF8, 0x1A, 0x62, 0x08, 0xE0, 0x00, 0xBF, + 0x92, 0xF8, 0x10, 0x02, 0x80, 0x07, 0x05, 0xD5, 0x01, 0x21, 0x13, 0xE0, 0xB2, 0xF8, 0x12, 0x62, + 0x86, 0x42, 0xF5, 0xDB, 0x73, 0xB1, 0x6C, 0x48, 0x00, 0x78, 0x01, 0x28, 0x03, 0xD0, 0x6B, 0x48, + 0x00, 0x78, 0x01, 0x28, 0x03, 0xD1, 0x92, 0xF8, 0x10, 0x02, 0x00, 0x07, 0x01, 0xD5, 0x01, 0x2C, + 0x00, 0xD1, 0x19, 0x46, 0x62, 0x48, 0x34, 0xB1, 0x19, 0xB1, 0x00, 0xBF, 0x92, 0xF8, 0x19, 0x22, + 0x42, 0x60, 0xA9, 0x70, 0x70, 0xBD, 0x00, 0x29, 0xF8, 0xD1, 0x00, 0x2B, 0xF6, 0xD0, 0x44, 0x68, + 0x00, 0x2C, 0xF6, 0xDD, 0x92, 0xF8, 0x10, 0x12, 0x0A, 0x07, 0x59, 0x49, 0x49, 0x68, 0xA1, 0xF1, + 0x01, 0x01, 0x02, 0xD5, 0x5D, 0x4A, 0x12, 0x78, 0x02, 0xB1, 0x41, 0x60, 0x19, 0x46, 0xE8, 0xE7, + 0x52, 0x48, 0x53, 0x49, 0x00, 0x68, 0x90, 0xF8, 0x10, 0x02, 0xC2, 0x06, 0x4F, 0xF0, 0x00, 0x00, + 0x03, 0xD4, 0x50, 0x4A, 0x90, 0x70, 0x48, 0x70, 0x48, 0x60, 0x08, 0x70, 0x70, 0x47, 0x10, 0xB5, + 0x04, 0x46, 0x4A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x10, 0x02, 0xC0, 0x06, 0x20, 0x46, 0x02, 0xD5, + 0xFF, 0xF7, 0x89, 0xFF, 0x01, 0xE0, 0xFF, 0xF7, 0x45, 0xFF, 0x46, 0x48, 0x82, 0x78, 0x4C, 0x48, + 0x41, 0x7B, 0x62, 0xF3, 0x07, 0x11, 0x41, 0x73, 0xA0, 0xF8, 0x2F, 0x40, 0x10, 0xBD, 0x2D, 0xE9, + 0xFC, 0x5F, 0x83, 0x46, 0x47, 0x48, 0x00, 0x25, 0x0A, 0x46, 0x00, 0x78, 0x2F, 0x46, 0x2C, 0x46, + 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x44, 0x48, 0x06, 0x78, 0x00, 0x78, 0x41, 0x00, 0x01, 0x2A, + 0x1B, 0xD0, 0xDF, 0xF8, 0xD8, 0x80, 0xDF, 0xF8, 0x04, 0xA1, 0xDF, 0xF8, 0x04, 0x91, 0xD8, 0xF8, + 0x00, 0x00, 0x90, 0xF8, 0x10, 0x22, 0x92, 0x06, 0x14, 0xD5, 0x32, 0x1B, 0xB0, 0xF9, 0x20, 0x12, + 0xCD, 0xE9, 0x00, 0x12, 0xB0, 0xF9, 0x1E, 0x32, 0x0A, 0xEB, 0x44, 0x02, 0x0B, 0xEB, 0x44, 0x01, + 0x09, 0xEB, 0x44, 0x00, 0x0C, 0xF0, 0x58, 0xFE, 0x09, 0xE0, 0x34, 0x48, 0x4C, 0x38, 0x11, 0xF0, + 0x98, 0xFB, 0x41, 0xE0, 0x0A, 0x46, 0x59, 0x46, 0x31, 0x48, 0x11, 0xF0, 0x13, 0xFB, 0x2F, 0x48, + 0x4C, 0x38, 0x34, 0xE0, 0x3A, 0xF9, 0x14, 0x20, 0x39, 0xF9, 0x14, 0x10, 0x51, 0x1A, 0x00, 0xD5, + 0x49, 0x42, 0xD8, 0xF8, 0x00, 0x30, 0x09, 0xB2, 0x93, 0xF8, 0x10, 0x22, 0x52, 0x06, 0x0B, 0xD5, + 0x20, 0x4A, 0x92, 0x79, 0x01, 0x2A, 0x07, 0xD1, 0x26, 0x4A, 0x12, 0x78, 0x22, 0xB9, 0xB3, 0xF8, + 0x22, 0x22, 0x8A, 0x42, 0x00, 0xDA, 0x01, 0x27, 0x30, 0xF9, 0x14, 0x20, 0x8A, 0x42, 0x02, 0xDA, + 0x93, 0xF8, 0x16, 0x32, 0x01, 0xE0, 0x93, 0xF8, 0x17, 0x32, 0x5A, 0x43, 0xC3, 0xF5, 0x80, 0x73, + 0x01, 0xFB, 0x03, 0x21, 0xCA, 0x17, 0x01, 0xEB, 0x12, 0x61, 0x09, 0x12, 0x20, 0xF8, 0x14, 0x10, + 0x30, 0xF9, 0x14, 0x10, 0xA9, 0x42, 0x00, 0xDD, 0x0D, 0x46, 0x64, 0x1C, 0x24, 0xB2, 0xB4, 0x42, + 0xC8, 0xDB, 0x28, 0x46, 0xFF, 0xF7, 0x73, 0xFF, 0x72, 0x00, 0x59, 0x46, 0x0F, 0x48, 0x11, 0xF0, + 0xD1, 0xFA, 0x03, 0x48, 0x07, 0x70, 0xBD, 0xE8, 0xFC, 0x9F, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x04, 0x05, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, 0xC1, 0x06, 0x10, 0x00, 0x0C, 0x05, 0x10, 0x00, + 0xC2, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0xC3, 0x06, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, + 0xE6, 0x43, 0x01, 0x20, 0xC0, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x46, 0x0A, 0x01, 0x20, + 0x92, 0x0A, 0x01, 0x20, 0x1C, 0x05, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x81, 0x46, 0xDD, 0xE9, + 0x09, 0xB5, 0x01, 0x20, 0x47, 0xF6, 0xFF, 0x77, 0x9A, 0x46, 0x84, 0x46, 0xFE, 0x43, 0x2C, 0x46, + 0x15, 0xE0, 0x00, 0xBF, 0x32, 0xF8, 0x14, 0x30, 0x31, 0xF8, 0x14, 0x80, 0xA3, 0xEB, 0x08, 0x03, + 0x1B, 0xB2, 0xBB, 0x42, 0x00, 0xDA, 0x1F, 0x46, 0xB3, 0x42, 0x00, 0xDD, 0x1E, 0x46, 0x00, 0x2B, + 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x0C, 0x02, 0xE0, 0x01, 0xDA, 0x4F, 0xF0, 0x00, 0x00, 0x64, 0x1E, + 0xE8, 0xD2, 0x20, 0xB1, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x00, 0x23, 0x09, 0xE0, 0x50, 0xEA, + 0x0C, 0x03, 0x06, 0xD0, 0x20, 0xB9, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x33, 0x46, 0x00, 0xE0, + 0x3B, 0x46, 0x00, 0x27, 0x3C, 0x46, 0x28, 0x46, 0xCB, 0xF1, 0x00, 0x0C, 0x0E, 0xE0, 0x00, 0xBF, + 0x32, 0xF8, 0x10, 0x60, 0x31, 0xF8, 0x10, 0x80, 0xA6, 0xEB, 0x08, 0x06, 0xF6, 0x1A, 0x36, 0xB2, + 0x56, 0x45, 0x03, 0xDA, 0x66, 0x45, 0x01, 0xDD, 0x37, 0x44, 0x64, 0x1C, 0x40, 0x1E, 0xEF, 0xD2, + 0x04, 0xB9, 0x01, 0x24, 0x97, 0xFB, 0xF4, 0xF0, 0x18, 0x44, 0x04, 0xE0, 0x31, 0xF8, 0x15, 0x20, + 0x02, 0x44, 0x29, 0xF8, 0x15, 0x20, 0x6D, 0x1E, 0xF8, 0xD2, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, + 0xF0, 0x41, 0x04, 0x46, 0x03, 0x46, 0xFE, 0x48, 0x15, 0x46, 0x0E, 0x46, 0x0A, 0x46, 0x01, 0x78, + 0xFC, 0x48, 0x00, 0xF0, 0x57, 0xFA, 0xFC, 0x48, 0x04, 0xF1, 0x08, 0x03, 0x1F, 0x46, 0x01, 0x78, + 0xF8, 0x48, 0x32, 0x46, 0x2A, 0x30, 0x00, 0xF0, 0x4D, 0xFA, 0x00, 0x2D, 0x07, 0xD0, 0x20, 0x46, + 0x11, 0xF0, 0xB0, 0xFB, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x11, 0xF0, 0xAB, 0xBB, 0xBD, 0xE8, + 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0x07, 0x46, 0x14, 0x46, 0x88, 0x46, 0x03, 0x20, 0x0F, 0xF0, + 0x3A, 0xFA, 0xEE, 0x4D, 0xEA, 0x4E, 0x00, 0x94, 0xEA, 0x48, 0x32, 0x78, 0x39, 0x46, 0x76, 0x38, + 0x2B, 0x68, 0x0C, 0xF0, 0xEF, 0xFD, 0x00, 0x94, 0xE7, 0x4C, 0xE6, 0x48, 0x41, 0x46, 0x22, 0x78, + 0x4C, 0x38, 0x2B, 0x68, 0x0C, 0xF0, 0xE6, 0xFD, 0xE5, 0x4D, 0x28, 0x68, 0x90, 0xF8, 0x30, 0x12, + 0xC9, 0x07, 0x1A, 0xD0, 0x32, 0x78, 0xB0, 0xF9, 0x34, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xDD, 0x49, + 0xB0, 0xF9, 0x32, 0x32, 0x76, 0x39, 0xDF, 0x4A, 0x08, 0x46, 0xFF, 0xF7, 0x55, 0xFF, 0x28, 0x68, + 0x22, 0x78, 0xB0, 0xF9, 0x38, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xD6, 0x49, 0xB0, 0xF9, 0x36, 0x32, + 0x4C, 0x39, 0xD9, 0x4A, 0x08, 0x46, 0xFF, 0xF7, 0x47, 0xFF, 0xD2, 0x49, 0x33, 0x78, 0xD5, 0x4A, + 0x76, 0x39, 0xD0, 0x48, 0x0C, 0xF0, 0xA1, 0xFD, 0xCE, 0x49, 0x23, 0x78, 0x4C, 0x39, 0xD2, 0x4A, + 0x01, 0xF1, 0x76, 0x00, 0x0C, 0xF0, 0x99, 0xFD, 0x28, 0x68, 0x90, 0xF8, 0x30, 0x12, 0x8A, 0x07, + 0x04, 0xD4, 0xCE, 0x4A, 0x12, 0x78, 0x8A, 0xB1, 0x49, 0x07, 0x0F, 0xD5, 0xC5, 0x49, 0x90, 0xF8, + 0x41, 0x32, 0x32, 0x78, 0x08, 0x46, 0x0C, 0xF0, 0xD8, 0xFD, 0x28, 0x68, 0xC1, 0x49, 0x22, 0x78, + 0x90, 0xF8, 0x41, 0x32, 0x2A, 0x31, 0x08, 0x46, 0x0C, 0xF0, 0xCF, 0xFD, 0xBD, 0xE8, 0xFC, 0x41, + 0x03, 0x20, 0x0F, 0xF0, 0xF3, 0xB9, 0x70, 0xB5, 0xC1, 0x4C, 0xC2, 0x49, 0x00, 0x25, 0xA5, 0x70, + 0x01, 0x20, 0x08, 0x70, 0xBA, 0x48, 0x25, 0x70, 0x65, 0x70, 0x00, 0x68, 0xB0, 0xF8, 0x3A, 0x02, + 0xA0, 0x80, 0x00, 0xF0, 0xE9, 0xF9, 0xFF, 0xF7, 0x6C, 0xFA, 0xA5, 0x60, 0xE5, 0x60, 0x70, 0xBD, + 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, 0xB7, 0x49, 0x07, 0x46, 0xB5, 0x4C, 0x0D, 0x78, 0x00, 0x20, + 0x08, 0x70, 0x60, 0x70, 0x00, 0xF0, 0xD8, 0xF9, 0xB3, 0x48, 0x2A, 0x46, 0x31, 0x46, 0x00, 0x78, + 0x00, 0x28, 0x38, 0x46, 0x02, 0xD0, 0xFF, 0xF7, 0xC3, 0xF9, 0x01, 0xE0, 0xFF, 0xF7, 0x69, 0xFF, + 0xAE, 0x48, 0x41, 0x78, 0xA6, 0x48, 0xA9, 0xB1, 0xA1, 0x78, 0x01, 0x29, 0x12, 0xD0, 0x00, 0x68, + 0xB0, 0xF9, 0x3C, 0x12, 0xAA, 0x4D, 0xA1, 0x80, 0x01, 0x22, 0x28, 0x46, 0xFF, 0xF7, 0x37, 0xFF, + 0xD5, 0xE9, 0x00, 0x01, 0x08, 0x43, 0x09, 0xD0, 0xD5, 0xE9, 0x02, 0x01, 0x08, 0x43, 0x05, 0xD0, + 0x01, 0x20, 0x04, 0xE0, 0x00, 0x68, 0xB0, 0xF9, 0x3A, 0x12, 0xEB, 0xE7, 0x00, 0x20, 0x20, 0x70, + 0x45, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0x04, 0x46, 0x9E, 0x48, 0xA7, 0xB0, 0x4F, 0xF0, 0x01, 0x0A, + 0x01, 0x78, 0x93, 0x48, 0x01, 0x29, 0x00, 0x68, 0x18, 0xD0, 0x94, 0x49, 0x09, 0x78, 0xC1, 0xB1, + 0xB0, 0xF9, 0x54, 0x62, 0x8A, 0x48, 0x01, 0x21, 0x00, 0x27, 0x00, 0x78, 0x80, 0x1E, 0x00, 0xF0, + 0xFF, 0x09, 0x89, 0x48, 0x03, 0x78, 0x5A, 0x1E, 0x02, 0xF0, 0xFF, 0x08, 0x92, 0x4A, 0x12, 0x78, + 0x02, 0xB1, 0x01, 0x27, 0x91, 0x4D, 0x22, 0x46, 0x83, 0x46, 0x12, 0xE0, 0xB0, 0xF9, 0x59, 0x62, + 0xE8, 0xE7, 0xB0, 0xF9, 0x52, 0x62, 0xE5, 0xE7, 0x38, 0x46, 0x05, 0xE0, 0x32, 0xF9, 0x10, 0xC0, + 0xAC, 0x45, 0x00, 0xDD, 0x65, 0x46, 0x40, 0x1C, 0x40, 0x45, 0xF7, 0xDD, 0x02, 0xEB, 0x43, 0x02, + 0x49, 0x1C, 0x49, 0x45, 0xF0, 0xDD, 0x5F, 0x46, 0x5A, 0x00, 0x04, 0xEB, 0x43, 0x01, 0x68, 0x46, + 0x11, 0xF0, 0x38, 0xF9, 0x82, 0x4A, 0x38, 0x78, 0x6B, 0x46, 0x12, 0x88, 0x41, 0x42, 0x02, 0xEB, + 0x41, 0x01, 0x09, 0xB2, 0x42, 0x00, 0x04, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x40, 0x00, 0x11, 0xF0, + 0x29, 0xF9, 0x38, 0x78, 0x69, 0x46, 0x42, 0x00, 0x08, 0x46, 0x0C, 0xF0, 0x44, 0xFD, 0x28, 0x1A, + 0x00, 0xB2, 0xB0, 0x42, 0x01, 0xDD, 0x4F, 0xF0, 0x00, 0x0A, 0x50, 0x46, 0x27, 0xB0, 0xC4, 0xE6, + 0x2D, 0xE9, 0xF0, 0x4F, 0x73, 0x49, 0x72, 0x4A, 0x00, 0x27, 0x0C, 0x68, 0xB2, 0xF9, 0x00, 0x20, + 0x4F, 0xF0, 0x01, 0x0B, 0x21, 0x8E, 0x3B, 0x46, 0x91, 0x42, 0x4F, 0xD1, 0x63, 0x49, 0x0A, 0x78, + 0x5F, 0x49, 0x0E, 0x68, 0xB2, 0xB1, 0xB6, 0xF9, 0x54, 0x12, 0x02, 0x25, 0x89, 0x46, 0x58, 0x49, + 0x4F, 0xF0, 0x00, 0x0A, 0x09, 0x78, 0xC9, 0x1E, 0x01, 0xF0, 0xFF, 0x0E, 0x56, 0x49, 0x09, 0x78, + 0x49, 0x1E, 0x01, 0xF0, 0xFF, 0x0C, 0x60, 0x49, 0x09, 0x78, 0x09, 0xB1, 0x4F, 0xF0, 0x01, 0x0A, + 0x32, 0x34, 0x2B, 0xE0, 0xB6, 0xF9, 0x52, 0x12, 0xE7, 0xE7, 0x52, 0x46, 0x1D, 0xE0, 0x00, 0xBF, + 0x34, 0xF8, 0x12, 0x10, 0x30, 0xF8, 0x12, 0x80, 0xA1, 0xEB, 0x08, 0x01, 0x09, 0xB2, 0x00, 0x29, + 0x01, 0xDB, 0x88, 0x46, 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x08, 0xB8, 0x45, 0x05, 0xDD, 0x00, 0x29, + 0x01, 0xDB, 0x0F, 0x46, 0x00, 0xE0, 0x4F, 0x42, 0x3F, 0xB2, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, + 0x49, 0x45, 0x01, 0xDD, 0x5B, 0x1C, 0x9B, 0xB2, 0x52, 0x1C, 0x62, 0x45, 0xE0, 0xDD, 0x96, 0xF8, + 0x30, 0x10, 0x6D, 0x1C, 0x04, 0xEB, 0x41, 0x04, 0x00, 0xEB, 0x41, 0x00, 0x75, 0x45, 0xD4, 0xDD, + 0x96, 0xF8, 0x56, 0x02, 0x98, 0x42, 0x01, 0xD2, 0x4F, 0xF0, 0x00, 0x0B, 0x46, 0x48, 0x20, 0xF8, + 0x33, 0x7F, 0x83, 0x70, 0x58, 0x46, 0x60, 0xE6, 0x2D, 0xE9, 0xF0, 0x41, 0x06, 0x46, 0x43, 0x48, + 0x00, 0x24, 0x00, 0x78, 0x00, 0x28, 0x5A, 0xD0, 0x3A, 0x48, 0x34, 0x4D, 0x00, 0x78, 0x88, 0xB1, + 0x3F, 0x48, 0x2F, 0x4B, 0x32, 0x49, 0x02, 0x68, 0x18, 0x68, 0x08, 0x31, 0xB0, 0xF8, 0x5D, 0x02, + 0x40, 0x42, 0x07, 0xB2, 0x00, 0x20, 0xC8, 0x80, 0x88, 0x80, 0x08, 0x60, 0x34, 0x48, 0xB0, 0xF9, + 0x00, 0x00, 0x25, 0xE0, 0x2C, 0x78, 0x01, 0x29, 0x01, 0xD0, 0x11, 0xB1, 0x3B, 0xE0, 0x01, 0x24, + 0x3A, 0xE0, 0x00, 0x24, 0x69, 0xE0, 0x00, 0xBF, 0x32, 0xF9, 0x10, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, + 0x16, 0xDA, 0xB1, 0xF8, 0x04, 0xC0, 0x0C, 0xF1, 0x01, 0x0C, 0xA1, 0xF8, 0x04, 0xC0, 0x32, 0xF9, + 0x10, 0xE0, 0xD1, 0xF8, 0x00, 0xC0, 0xF4, 0x44, 0xC1, 0xF8, 0x00, 0xC0, 0x32, 0xF9, 0x10, 0xC0, + 0xBC, 0x45, 0x05, 0xDA, 0xB1, 0xF8, 0x06, 0xC0, 0x0C, 0xF1, 0x01, 0x0C, 0xA1, 0xF8, 0x06, 0xC0, + 0x40, 0x1E, 0xE1, 0xD2, 0x08, 0x68, 0x40, 0x42, 0x08, 0x60, 0x15, 0x48, 0x19, 0x68, 0x08, 0x30, + 0x02, 0x68, 0xB1, 0xF8, 0x5F, 0x32, 0x9A, 0x42, 0x3F, 0xDD, 0xB0, 0xF9, 0x06, 0x00, 0x91, 0xF8, + 0x61, 0x12, 0x88, 0x42, 0x39, 0xDD, 0x1B, 0x48, 0x11, 0x4A, 0xB0, 0xF9, 0x00, 0x10, 0x30, 0x46, + 0x00, 0xF0, 0x1E, 0xF9, 0x04, 0x46, 0x7C, 0xB3, 0x00, 0xF0, 0xF0, 0xF8, 0x2F, 0xE0, 0x3F, 0xE0, + 0xB9, 0x06, 0x10, 0x00, 0x36, 0x0B, 0x01, 0x20, 0xBA, 0x06, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, 0x1C, 0x05, 0x10, 0x00, + 0x0C, 0x05, 0x10, 0x00, 0x51, 0x07, 0x10, 0x00, 0xC0, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0x80, 0x24, 0x10, 0x00, 0x21, 0x05, 0x10, 0x00, 0xBF, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0xCA, 0x06, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0xEC, 0x06, 0x10, 0x00, + 0xE0, 0x06, 0x10, 0x00, 0x74, 0x06, 0x10, 0x00, 0xFF, 0xE7, 0x00, 0xF0, 0xD5, 0xF8, 0x50, 0x4E, + 0x28, 0x78, 0x31, 0x78, 0x88, 0x42, 0x06, 0xD0, 0x08, 0xB1, 0x01, 0x21, 0x00, 0xE0, 0x00, 0x21, + 0x06, 0x20, 0x0B, 0xF0, 0x8F, 0xF8, 0x28, 0x78, 0x30, 0x70, 0x0C, 0xB1, 0x01, 0x20, 0xDE, 0xE5, + 0x00, 0x20, 0xDC, 0xE5, 0x70, 0xB5, 0x03, 0x20, 0x0F, 0xF0, 0x1D, 0xF8, 0x00, 0xF0, 0x48, 0xF8, + 0x04, 0x46, 0x03, 0x20, 0x0F, 0xF0, 0x32, 0xF8, 0x42, 0x49, 0xC8, 0x7B, 0x64, 0xF3, 0x05, 0x10, + 0xC8, 0x73, 0x41, 0x48, 0x01, 0x78, 0x21, 0xB1, 0x00, 0x21, 0x01, 0x70, 0x20, 0x46, 0x00, 0xF0, + 0x35, 0xF9, 0x3E, 0x4D, 0x3E, 0x48, 0x21, 0x46, 0x2A, 0x78, 0x00, 0x68, 0xFF, 0xF7, 0x3C, 0xFF, + 0xA8, 0x70, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x1D, 0x46, 0x4F, 0xF0, 0x00, 0x08, 0xC5, 0xE9, + 0x00, 0x88, 0x91, 0x46, 0x82, 0x46, 0x0C, 0x46, 0x11, 0xE0, 0x00, 0xBF, 0x3A, 0xF9, 0x14, 0x10, + 0x49, 0x45, 0x0C, 0xDD, 0xD5, 0xE9, 0x00, 0x67, 0x4F, 0xF0, 0x01, 0x08, 0x22, 0x46, 0x40, 0x46, + 0x00, 0x21, 0x10, 0xF0, 0xA0, 0xFF, 0x06, 0x43, 0x0F, 0x43, 0xC5, 0xE9, 0x00, 0x67, 0x64, 0x1E, + 0xEC, 0xD2, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x2A, 0x48, 0x00, 0x21, 0xC0, 0xE9, 0x00, 0x11, + 0xC0, 0xE9, 0x02, 0x11, 0x08, 0x46, 0x28, 0x49, 0x08, 0x76, 0x28, 0x49, 0x08, 0x76, 0x70, 0x47, + 0x2D, 0xE9, 0xF0, 0x41, 0x26, 0x4C, 0x20, 0x78, 0x02, 0x28, 0x33, 0xD9, 0x25, 0x4E, 0x30, 0x68, + 0x90, 0xF8, 0x50, 0x02, 0x41, 0x07, 0x24, 0x48, 0x00, 0x68, 0x02, 0xD5, 0x23, 0x49, 0x09, 0x78, + 0x79, 0xB1, 0xFF, 0xF7, 0x36, 0xFE, 0x05, 0x46, 0x30, 0x68, 0x90, 0xF8, 0x50, 0x02, 0x00, 0x07, + 0x1F, 0xD5, 0x22, 0x78, 0x1E, 0x4B, 0x1F, 0x49, 0x02, 0x2A, 0x1A, 0xDB, 0x1E, 0x4C, 0x50, 0x1E, + 0x07, 0xE0, 0xFF, 0xF7, 0x85, 0xFE, 0xEE, 0xE7, 0x33, 0xF9, 0x10, 0x70, 0xA7, 0x42, 0x00, 0xDD, + 0x3C, 0x46, 0x40, 0x1E, 0xF8, 0xD1, 0x98, 0x1C, 0x92, 0x1E, 0x0C, 0xF0, 0xB4, 0xFB, 0x20, 0x1A, + 0x01, 0xB2, 0x30, 0x68, 0xB0, 0xF9, 0x57, 0x02, 0x81, 0x42, 0x02, 0xDD, 0x35, 0xB1, 0x02, 0x20, + 0x55, 0xE5, 0x0D, 0xB1, 0x00, 0x20, 0x52, 0xE5, 0x01, 0x20, 0x50, 0xE5, 0x03, 0x20, 0x4E, 0xE5, + 0x1D, 0x05, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x20, 0x05, 0x10, 0x00, 0x0C, 0x05, 0x10, 0x00, + 0xE0, 0x06, 0x10, 0x00, 0x80, 0x24, 0x10, 0x00, 0x58, 0x23, 0x10, 0x00, 0x98, 0x23, 0x10, 0x00, + 0xB9, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, 0x21, 0x05, 0x10, 0x00, + 0x6A, 0x4A, 0x01, 0x20, 0x92, 0x0A, 0x01, 0x20, 0x00, 0x80, 0xFF, 0xFF, 0x53, 0x48, 0x00, 0x21, + 0xC1, 0x70, 0x02, 0x78, 0x00, 0x2A, 0x0E, 0xD1, 0x82, 0x78, 0x51, 0x4B, 0x52, 0x1C, 0xD2, 0xB2, + 0x82, 0x70, 0x1B, 0x68, 0x93, 0xF8, 0x62, 0x32, 0x03, 0xF0, 0x0F, 0x03, 0x93, 0x42, 0x02, 0xD2, + 0x01, 0x22, 0x02, 0x70, 0x81, 0x70, 0x70, 0x47, 0x48, 0x48, 0x00, 0x21, 0x81, 0x70, 0x02, 0x78, + 0x00, 0x2A, 0x0C, 0xD0, 0xC2, 0x78, 0x46, 0x4B, 0x52, 0x1C, 0xD2, 0xB2, 0xC2, 0x70, 0x1B, 0x68, + 0x93, 0xF8, 0x62, 0x32, 0xB2, 0xEB, 0x13, 0x1F, 0x01, 0xD9, 0x01, 0x70, 0xC1, 0x70, 0x70, 0x47, + 0x2D, 0xE9, 0xF7, 0x4F, 0x86, 0xB0, 0x8B, 0x46, 0xD2, 0xE9, 0x00, 0x01, 0xCD, 0xE9, 0x02, 0x01, + 0xD2, 0xE9, 0x02, 0x01, 0xCD, 0xE9, 0x04, 0x01, 0x02, 0xA8, 0x11, 0xF0, 0xA3, 0xF8, 0x04, 0xA8, + 0x11, 0xF0, 0xA0, 0xF8, 0x37, 0x48, 0x00, 0x27, 0xB9, 0x46, 0x06, 0x78, 0x31, 0xE0, 0xF1, 0xB2, + 0x06, 0x98, 0x11, 0xF0, 0xAD, 0xF8, 0x82, 0x46, 0x33, 0x48, 0x32, 0x46, 0x00, 0x21, 0x05, 0x78, + 0x01, 0x20, 0x10, 0xF0, 0xE0, 0xFE, 0x02, 0x9A, 0x00, 0xEA, 0x02, 0x04, 0x03, 0x98, 0x01, 0xEA, + 0x00, 0x08, 0xDD, 0xE9, 0x04, 0x01, 0xCD, 0xE9, 0x00, 0x01, 0x18, 0xE0, 0x3A, 0xF9, 0x15, 0x10, + 0x59, 0x45, 0x14, 0xDD, 0x54, 0xEA, 0x08, 0x00, 0x0F, 0xD0, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x10, 0xF0, 0xC9, 0xFE, 0xDD, 0xE9, 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x04, 0xD0, + 0x09, 0xF1, 0x01, 0x00, 0x1F, 0xFA, 0x80, 0xF9, 0x01, 0xE0, 0x7F, 0x1C, 0xBF, 0xB2, 0x6D, 0x1E, + 0xE4, 0xD2, 0x76, 0x1E, 0xCB, 0xD2, 0x1A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x5B, 0x12, 0xB9, 0x42, + 0x07, 0xD8, 0x90, 0xF8, 0x5C, 0x12, 0x49, 0x45, 0x03, 0xD3, 0x01, 0x20, 0x09, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0x00, 0x20, 0xFA, 0xE7, 0x11, 0x48, 0x10, 0xB5, 0x41, 0x78, 0x01, 0x70, 0x00, 0x21, + 0x81, 0x70, 0xC1, 0x70, 0xFF, 0xF7, 0x0F, 0xFD, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0xCC, 0xBF, + 0x0A, 0x48, 0x00, 0x21, 0x0A, 0x4A, 0x01, 0x70, 0x41, 0x70, 0x12, 0x68, 0x92, 0xF8, 0x50, 0x22, + 0x92, 0x07, 0x00, 0xD5, 0x01, 0x21, 0x41, 0x71, 0x01, 0x71, 0x70, 0x47, 0x03, 0x49, 0x4A, 0x79, + 0x01, 0x2A, 0x02, 0xD1, 0x00, 0x28, 0x00, 0xD1, 0x48, 0x71, 0x70, 0x47, 0x1C, 0x05, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x4F, + 0xCE, 0x4B, 0x83, 0xB0, 0x1B, 0x68, 0xB3, 0xF9, 0xD2, 0x42, 0xB3, 0xF9, 0xD4, 0xE2, 0x99, 0xE0, + 0x47, 0xF6, 0xFF, 0x76, 0xF7, 0x43, 0x06, 0x9D, 0x08, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x15, 0x30, + 0xB3, 0x42, 0x00, 0xDA, 0x1E, 0x46, 0xBB, 0x42, 0x00, 0xDD, 0x1F, 0x46, 0x6D, 0x1E, 0xF5, 0xD1, + 0xAB, 0x46, 0x00, 0x2F, 0x01, 0xDA, 0xBB, 0x46, 0x02, 0xE0, 0x00, 0x2E, 0x00, 0xDD, 0xB3, 0x46, + 0x00, 0x26, 0x37, 0x46, 0xB2, 0x46, 0x35, 0x46, 0xB1, 0x46, 0x06, 0x9B, 0x13, 0xE0, 0x00, 0xBF, + 0x31, 0xF9, 0x13, 0x80, 0xA8, 0xEB, 0x0B, 0x0C, 0xA4, 0x45, 0x0C, 0xDA, 0x0C, 0xEB, 0x04, 0x08, + 0xB8, 0xF1, 0x00, 0x0F, 0x07, 0xDD, 0x03, 0xFB, 0x03, 0x77, 0x03, 0xFB, 0x0C, 0x55, 0x1E, 0x44, + 0xE2, 0x44, 0x09, 0xF1, 0x01, 0x09, 0x5B, 0x1E, 0xEA, 0xD1, 0x07, 0xFB, 0x09, 0xF3, 0x06, 0xFB, + 0x16, 0x33, 0x02, 0x93, 0x05, 0xFB, 0x09, 0xF3, 0x06, 0xFB, 0x1A, 0x33, 0x07, 0xFB, 0x0A, 0xF7, + 0x01, 0x93, 0x05, 0xFB, 0x16, 0x73, 0x4F, 0xF0, 0x00, 0x0C, 0x00, 0x93, 0x67, 0x46, 0x66, 0x46, + 0xE2, 0x46, 0x06, 0x9B, 0x28, 0xE0, 0xDD, 0xF8, 0x08, 0x80, 0x00, 0x25, 0xB8, 0xF1, 0x00, 0x0F, + 0x0D, 0xD0, 0xDD, 0xE9, 0x00, 0x58, 0x08, 0xFB, 0x03, 0x58, 0x02, 0x9D, 0x98, 0xFB, 0xF5, 0xF5, + 0xA5, 0x42, 0x01, 0xDD, 0x25, 0x46, 0x02, 0xE0, 0xE5, 0x42, 0x00, 0xD5, 0x65, 0x42, 0x31, 0xF8, + 0x13, 0x80, 0x5D, 0x44, 0xA8, 0xEB, 0x05, 0x05, 0x2D, 0xB2, 0x7F, 0x1C, 0xA9, 0x46, 0xAC, 0x44, + 0x75, 0x45, 0x07, 0xDA, 0x05, 0xEB, 0x0E, 0x08, 0xB8, 0xF1, 0x00, 0x0F, 0x02, 0xDD, 0x4E, 0x44, + 0x0A, 0xF1, 0x01, 0x0A, 0x20, 0xF8, 0x13, 0x90, 0x5B, 0x1E, 0xD4, 0xD1, 0x9C, 0xFB, 0xF7, 0xF5, + 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0x96, 0xFB, 0xFA, 0xF3, 0x00, 0x2D, + 0x01, 0xDB, 0x2F, 0x46, 0x00, 0xE0, 0x6F, 0x42, 0x1E, 0x1E, 0x00, 0xDA, 0x5E, 0x42, 0xB7, 0xEB, + 0x46, 0x0F, 0x00, 0xDD, 0x1D, 0x46, 0x06, 0x9B, 0x05, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x13, 0x60, + 0x76, 0x1B, 0x20, 0xF8, 0x13, 0x60, 0x5B, 0x1E, 0xF8, 0xD1, 0x06, 0x9B, 0x01, 0xEB, 0x43, 0x01, + 0x00, 0xEB, 0x43, 0x00, 0x52, 0x1E, 0xBF, 0xF4, 0x63, 0xAF, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x2D, 0xE9, 0xF7, 0x4F, 0x79, 0x4D, 0x7A, 0x4C, 0x7A, 0x4F, 0x28, 0x68, 0x0E, 0x46, 0x90, 0xF8, + 0xD0, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x3C, 0x68, 0x03, 0x20, 0x0E, 0xF0, 0x0C, 0xFE, 0x77, 0x48, + 0xDF, 0xF8, 0xD4, 0xB1, 0x31, 0x46, 0x02, 0x68, 0xBB, 0xF9, 0x00, 0x30, 0x20, 0x46, 0x0C, 0xF0, + 0xA4, 0xF9, 0x03, 0x20, 0x0E, 0xF0, 0x1A, 0xFE, 0x28, 0x68, 0xDF, 0xF8, 0xC4, 0xA1, 0x71, 0x4E, + 0x90, 0xF8, 0xD0, 0x02, 0xC0, 0x07, 0x06, 0xD0, 0x9A, 0xF8, 0x00, 0x30, 0x32, 0x78, 0x21, 0x46, + 0x67, 0x48, 0xFF, 0xF7, 0x2B, 0xFF, 0xB9, 0x46, 0x65, 0x4A, 0x33, 0x78, 0x4F, 0xF0, 0x00, 0x08, + 0x54, 0x46, 0x38, 0x68, 0x16, 0xE0, 0x00, 0xBF, 0xA0, 0xF8, 0x00, 0x80, 0x01, 0x21, 0x09, 0xE0, + 0x00, 0xEB, 0x41, 0x07, 0x32, 0xF8, 0x11, 0xC0, 0x37, 0xF8, 0x02, 0x7C, 0x67, 0x44, 0x20, 0xF8, + 0x11, 0x70, 0x49, 0x1C, 0x27, 0x78, 0xB9, 0x42, 0xF2, 0xDB, 0xF9, 0xB2, 0x02, 0xEB, 0x41, 0x02, + 0x00, 0xEB, 0x41, 0x00, 0x5B, 0x1E, 0xE7, 0xD2, 0x5B, 0x48, 0x5C, 0x4F, 0x02, 0x9B, 0x02, 0x68, + 0xD9, 0xF8, 0x00, 0x10, 0x38, 0x68, 0x00, 0xF0, 0x66, 0xFA, 0x28, 0x68, 0x90, 0xF8, 0xD0, 0x02, + 0x80, 0x07, 0x06, 0xD5, 0x23, 0x78, 0x32, 0x78, 0x39, 0x68, 0x00, 0x98, 0x00, 0xF0, 0x1C, 0xF8, + 0x06, 0xE0, 0xBB, 0xF9, 0x00, 0x00, 0x39, 0x68, 0x42, 0x00, 0x00, 0x98, 0x10, 0xF0, 0xA2, 0xFD, + 0x28, 0x68, 0x90, 0xF8, 0xD0, 0x02, 0x00, 0x07, 0x08, 0xD5, 0x00, 0x99, 0x23, 0x78, 0x32, 0x78, + 0x03, 0xB0, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0x03, 0xBC, 0xBD, 0xE8, 0xFE, 0x8F, + 0x47, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0xA7, 0xB0, 0x1C, 0x46, + 0x0D, 0x46, 0x06, 0x46, 0x17, 0x46, 0xEA, 0x46, 0x0D, 0xF1, 0x4C, 0x0B, 0x3C, 0xE0, 0x00, 0x22, + 0x60, 0x1E, 0x00, 0xF0, 0xFF, 0x09, 0x11, 0x46, 0x10, 0x46, 0x11, 0xE0, 0x35, 0xF9, 0x10, 0x30, + 0x1A, 0x44, 0x43, 0x1C, 0x92, 0xFB, 0xF3, 0xFC, 0x2A, 0xF8, 0x10, 0xC0, 0xA9, 0xEB, 0x00, 0x0C, + 0x40, 0x1C, 0x35, 0xF9, 0x1C, 0x80, 0x41, 0x44, 0x91, 0xFB, 0xF3, 0xF3, 0x2B, 0xF8, 0x1C, 0x30, + 0xA0, 0x42, 0xEB, 0xDB, 0x20, 0x46, 0x52, 0x46, 0x5B, 0x46, 0x0C, 0xE0, 0x32, 0xF9, 0x10, 0x10, + 0x33, 0xF9, 0x10, 0xC0, 0x61, 0x44, 0x35, 0xF8, 0x10, 0xC0, 0x01, 0xEB, 0xD1, 0x71, 0xAC, 0xEB, + 0x61, 0x01, 0x26, 0xF8, 0x10, 0x10, 0x40, 0x1E, 0xF0, 0xD2, 0x20, 0x48, 0x00, 0x68, 0x90, 0xF8, + 0xD0, 0x02, 0x40, 0x07, 0x04, 0xD5, 0x31, 0x46, 0x22, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x08, 0xF8, + 0x05, 0xEB, 0x44, 0x05, 0x06, 0xEB, 0x44, 0x06, 0x7F, 0x1E, 0xC0, 0xD2, 0x27, 0xB0, 0x35, 0xE7, + 0xF0, 0xB5, 0x16, 0x4B, 0x00, 0x26, 0x35, 0x46, 0xD3, 0xF8, 0x00, 0xE0, 0x34, 0x46, 0x13, 0x46, + 0xBE, 0xF9, 0xD6, 0x72, 0xC7, 0xF1, 0x00, 0x0C, 0x06, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x13, 0x70, + 0x67, 0x45, 0x01, 0xDA, 0x3E, 0x44, 0x6D, 0x1C, 0x5B, 0x1E, 0xF7, 0xD2, 0x00, 0x2D, 0x01, 0xDD, + 0x96, 0xFB, 0xF5, 0xF4, 0xBE, 0xF8, 0xD8, 0x32, 0x5E, 0x42, 0xA6, 0x42, 0x00, 0xDD, 0x1C, 0x44, + 0x53, 0x1B, 0x63, 0x43, 0x93, 0xFB, 0xF2, 0xF3, 0x05, 0xE0, 0x00, 0xBF, 0x31, 0xF8, 0x12, 0x40, + 0xE4, 0x1A, 0x20, 0xF8, 0x12, 0x40, 0x52, 0x1E, 0xF8, 0xD2, 0xF0, 0xBD, 0x20, 0x07, 0x10, 0x00, + 0x3C, 0x0C, 0x01, 0x20, 0x2C, 0x05, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, + 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, 0xE4, 0x06, 0x10, 0x00, + 0xBF, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x1E, 0x46, 0x15, 0x46, 0x88, 0x46, 0x83, 0x46, + 0x00, 0x24, 0x4F, 0xF0, 0xAA, 0x09, 0x0A, 0x9F, 0x4F, 0xE0, 0x30, 0x5D, 0x08, 0xB9, 0x28, 0x5D, + 0xF0, 0xB3, 0x06, 0xF8, 0x04, 0x90, 0x38, 0xF9, 0x14, 0x00, 0x00, 0xF0, 0xCE, 0xF8, 0x28, 0xF8, + 0x14, 0x00, 0x28, 0x5D, 0xA0, 0xB3, 0x05, 0xEB, 0x04, 0x0A, 0x1A, 0xF8, 0x01, 0x1C, 0x81, 0x42, + 0x1C, 0xD0, 0xAA, 0x28, 0x1A, 0xD0, 0x0A, 0xF8, 0x01, 0x9C, 0x0B, 0xEB, 0x44, 0x01, 0x00, 0x91, + 0x31, 0xF9, 0x02, 0x0C, 0x00, 0xF0, 0xB9, 0xF8, 0x00, 0x99, 0x21, 0xF8, 0x02, 0x0C, 0x31, 0x19, + 0x01, 0xF8, 0x01, 0x9C, 0x08, 0xEB, 0x44, 0x01, 0x00, 0x91, 0x31, 0xF9, 0x02, 0x0C, 0x00, 0xF0, + 0xAC, 0xF8, 0x00, 0x99, 0x21, 0xF8, 0x02, 0x0C, 0x28, 0x5D, 0x88, 0xB1, 0x9A, 0xF8, 0x01, 0x10, + 0x28, 0x5D, 0x81, 0x42, 0x18, 0xD0, 0xAA, 0x28, 0x16, 0xD0, 0x8A, 0xF8, 0x01, 0x90, 0x0B, 0xEB, + 0x44, 0x0A, 0xBA, 0xF9, 0x02, 0x00, 0x00, 0xF0, 0x98, 0xF8, 0xAA, 0xF8, 0x02, 0x00, 0x00, 0xE0, + 0x0A, 0xE0, 0x31, 0x19, 0x08, 0xEB, 0x44, 0x0A, 0x81, 0xF8, 0x01, 0x90, 0xBA, 0xF9, 0x02, 0x00, + 0x00, 0xF0, 0x8B, 0xF8, 0xAA, 0xF8, 0x02, 0x00, 0x64, 0x1C, 0xBC, 0x42, 0xAD, 0xD3, 0xBD, 0xE8, + 0xF8, 0x8F, 0x4A, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x48, 0x49, 0x08, 0x60, 0x70, 0x47, + 0x2D, 0xE9, 0xF7, 0x4F, 0x46, 0x48, 0x8A, 0xB0, 0x90, 0x46, 0x00, 0x78, 0x0C, 0x46, 0x00, 0x28, + 0x70, 0xD0, 0x44, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x00, 0x04, 0x80, 0x07, 0x6A, 0xD5, 0x42, 0x48, + 0x04, 0x90, 0x42, 0x48, 0xDF, 0xF8, 0xF4, 0xA0, 0x01, 0x25, 0x07, 0x78, 0x4F, 0xF0, 0x00, 0x0B, + 0xDA, 0xF8, 0x00, 0x90, 0x20, 0xE0, 0x01, 0x20, 0xA8, 0x40, 0x10, 0xEA, 0x09, 0x0F, 0x1A, 0xD1, + 0x3B, 0x48, 0x00, 0xEB, 0x85, 0x06, 0x04, 0x98, 0xB1, 0x78, 0x10, 0xF0, 0x09, 0xFE, 0xB2, 0x78, + 0x5B, 0x46, 0x0D, 0xE0, 0x31, 0x78, 0x05, 0xE0, 0x10, 0xF8, 0x01, 0xC0, 0xAC, 0x45, 0x00, 0xD1, + 0x43, 0x54, 0x49, 0x1C, 0x96, 0xF8, 0x01, 0xC0, 0x8C, 0x45, 0xF5, 0xDA, 0x28, 0x30, 0x52, 0x1C, + 0xF1, 0x78, 0x91, 0x42, 0xEE, 0xDA, 0x6D, 0x1C, 0xBD, 0x42, 0xDC, 0xD9, 0x00, 0x21, 0x0A, 0x98, + 0x10, 0xF0, 0xF4, 0xFD, 0x01, 0x90, 0x01, 0x21, 0x0A, 0x98, 0x10, 0xF0, 0xEF, 0xFD, 0x08, 0x90, + 0x00, 0x21, 0x25, 0x48, 0x10, 0xF0, 0xE4, 0xFD, 0x81, 0x46, 0x01, 0x21, 0x22, 0x48, 0x10, 0xF0, + 0xDF, 0xFD, 0x06, 0x46, 0x65, 0x1E, 0xE9, 0xB2, 0x0A, 0x98, 0x10, 0xF0, 0xDF, 0xFD, 0xA4, 0x1E, + 0x06, 0x90, 0xE1, 0xB2, 0x0A, 0x98, 0x10, 0xF0, 0xD9, 0xFD, 0x07, 0x46, 0xE9, 0xB2, 0x1A, 0x48, + 0x10, 0xF0, 0xCE, 0xFD, 0x05, 0x46, 0xE1, 0xB2, 0x17, 0x48, 0x10, 0xF0, 0xC9, 0xFD, 0x04, 0x46, + 0x33, 0x46, 0x4A, 0x46, 0xCD, 0xF8, 0x00, 0x80, 0x08, 0x99, 0x01, 0x98, 0xFF, 0xF7, 0x2A, 0xFF, + 0x23, 0x46, 0x2A, 0x46, 0x39, 0x46, 0xCD, 0xF8, 0x00, 0x80, 0x06, 0x98, 0xFF, 0xF7, 0x22, 0xFF, + 0xCA, 0xF8, 0x00, 0xB0, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0A, 0x49, 0x09, 0x68, 0x91, 0xF8, + 0x08, 0x24, 0x42, 0x43, 0x64, 0x20, 0x92, 0xFB, 0xF0, 0xF0, 0xB1, 0xF8, 0x06, 0x24, 0x00, 0xB2, + 0x82, 0x42, 0x01, 0xDA, 0xB1, 0xF9, 0x06, 0x04, 0x70, 0x47, 0x00, 0x00, 0x24, 0x05, 0x10, 0x00, + 0x80, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xB4, 0x18, 0x01, 0x20, 0x15, 0x06, 0x10, 0x00, + 0x4C, 0x1C, 0x01, 0x20, 0x2D, 0xE9, 0xF0, 0x4F, 0xFE, 0x4C, 0x80, 0x25, 0xFE, 0x4E, 0x23, 0x68, + 0x93, 0xF8, 0x31, 0x10, 0x93, 0xF8, 0x30, 0x00, 0x01, 0xFB, 0x00, 0xF2, 0x02, 0xE0, 0x00, 0xBF, + 0x26, 0xF8, 0x12, 0x50, 0x52, 0x1E, 0xFB, 0xD2, 0x93, 0xF8, 0xAA, 0x22, 0xA6, 0x46, 0x12, 0x07, + 0x4F, 0xF0, 0x64, 0x08, 0x31, 0xD5, 0x4A, 0x1E, 0x02, 0xFB, 0x00, 0xFA, 0xDF, 0xF8, 0xC8, 0xB3, + 0x03, 0xF5, 0x94, 0x69, 0x02, 0x46, 0x26, 0xE0, 0x19, 0xF8, 0x02, 0x30, 0x0A, 0xEB, 0x02, 0x04, + 0xDB, 0x01, 0xB3, 0xFB, 0xF8, 0xF3, 0x0B, 0xEB, 0x44, 0x05, 0x0C, 0x46, 0x19, 0xE0, 0x80, 0x2B, + 0x05, 0xDD, 0xC3, 0xF1, 0x80, 0x06, 0x66, 0x43, 0x96, 0xFB, 0xF1, 0xF6, 0x06, 0xE0, 0xA3, 0xF1, + 0x80, 0x06, 0x06, 0xFB, 0x04, 0xF7, 0x97, 0xFB, 0xF1, 0xF7, 0xF6, 0x1B, 0xB5, 0xF9, 0x00, 0x70, + 0x80, 0x36, 0x77, 0x43, 0xFE, 0x17, 0x07, 0xEB, 0x56, 0x66, 0xF6, 0x11, 0x2E, 0x80, 0xA5, 0xEB, + 0x40, 0x05, 0x64, 0x1E, 0xE3, 0xD2, 0x52, 0x1E, 0xD6, 0xD2, 0xDE, 0xF8, 0x00, 0x20, 0xF2, 0x46, + 0x92, 0xF8, 0xAA, 0x32, 0xDB, 0x06, 0x2F, 0xD5, 0x02, 0xF5, 0x98, 0x69, 0xD6, 0x4B, 0x4A, 0x1E, + 0x42, 0x43, 0x03, 0xEB, 0x42, 0x05, 0x0A, 0x46, 0x24, 0xE0, 0x00, 0xBF, 0x19, 0xF8, 0x02, 0x30, + 0xDB, 0x01, 0xB3, 0xFB, 0xF8, 0xF6, 0x03, 0x46, 0x18, 0xE0, 0x80, 0x2E, 0x05, 0xDD, 0xC6, 0xF1, + 0x80, 0x04, 0x5C, 0x43, 0x94, 0xFB, 0xF0, 0xF4, 0x06, 0xE0, 0xA6, 0xF1, 0x80, 0x04, 0x04, 0xFB, + 0x03, 0xF7, 0x97, 0xFB, 0xF0, 0xF7, 0xE4, 0x1B, 0x35, 0xF9, 0x13, 0x70, 0x80, 0x34, 0x67, 0x43, + 0xFC, 0x17, 0x07, 0xEB, 0x54, 0x64, 0xE4, 0x11, 0x25, 0xF8, 0x13, 0x40, 0x5B, 0x1E, 0xE4, 0xD2, + 0xA5, 0xEB, 0x40, 0x05, 0x52, 0x1E, 0xD9, 0xD2, 0xDA, 0xF8, 0x00, 0x40, 0x94, 0xF8, 0xAB, 0x22, + 0xD2, 0x07, 0x20, 0xD0, 0xBC, 0x4E, 0x00, 0x23, 0x04, 0xF5, 0x9C, 0x64, 0x19, 0xE0, 0x00, 0xBF, + 0x03, 0xFB, 0x00, 0xF2, 0x06, 0xEB, 0x42, 0x07, 0x00, 0x22, 0x0F, 0xE0, 0xA5, 0x5C, 0xED, 0x01, + 0xB5, 0xFB, 0xF8, 0xFC, 0x37, 0xF9, 0x12, 0x50, 0x05, 0xFB, 0x0C, 0xF5, 0x4F, 0xEA, 0xE5, 0x7C, + 0x05, 0xEB, 0x5C, 0x65, 0xED, 0x11, 0x27, 0xF8, 0x12, 0x50, 0x52, 0x1C, 0x82, 0x42, 0xED, 0xD3, + 0x5B, 0x1C, 0x8B, 0x42, 0xE4, 0xD3, 0xBD, 0xE8, 0xF0, 0x8F, 0x08, 0xB5, 0x00, 0x93, 0x80, 0x23, + 0x0B, 0xF0, 0x10, 0xFF, 0x08, 0xBD, 0x08, 0xB5, 0x00, 0x93, 0x13, 0x46, 0xA7, 0x4A, 0xB2, 0xF9, + 0x00, 0x20, 0x0B, 0xF0, 0x17, 0xFF, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x5F, 0x00, 0xF0, 0x36, 0xFD, + 0xA0, 0x4F, 0xDF, 0xF8, 0x8C, 0xA2, 0x38, 0x68, 0x9A, 0xF8, 0x01, 0x40, 0xB0, 0xF9, 0x00, 0x13, + 0xB0, 0xF9, 0x22, 0x33, 0xB0, 0xF9, 0x42, 0x23, 0x01, 0x2C, 0x50, 0xD0, 0x02, 0x2C, 0x04, 0xD3, + 0xB0, 0xF8, 0x04, 0x43, 0x0C, 0xB1, 0xB0, 0xF9, 0x04, 0x13, 0x9A, 0x4C, 0xA5, 0x79, 0x9D, 0xB1, + 0x90, 0xF8, 0x69, 0x53, 0x64, 0x26, 0x05, 0xFB, 0x01, 0xFC, 0x9C, 0xFB, 0xF6, 0xFC, 0x61, 0x44, + 0x05, 0xFB, 0x03, 0xFC, 0x55, 0x43, 0x9C, 0xFB, 0xF6, 0xFC, 0x95, 0xFB, 0xF6, 0xF5, 0x63, 0x44, + 0x2A, 0x44, 0x09, 0xB2, 0x1B, 0xB2, 0x12, 0xB2, 0x8F, 0x4E, 0x90, 0x4D, 0xDF, 0xF8, 0x40, 0xC2, + 0x31, 0x80, 0x2B, 0x80, 0xAC, 0xF8, 0x00, 0x20, 0x90, 0xF8, 0x02, 0x73, 0xC9, 0x1B, 0x8D, 0x4F, + 0x39, 0x80, 0x90, 0xF8, 0x24, 0x13, 0x5B, 0x1A, 0x8B, 0x49, 0x0B, 0x80, 0x90, 0xF8, 0x44, 0x33, + 0xD3, 0x1A, 0x8A, 0x4A, 0x13, 0x80, 0x23, 0x78, 0x53, 0xB1, 0x89, 0x4B, 0x1B, 0x78, 0x3B, 0xB1, + 0xB0, 0xF8, 0x6C, 0x32, 0x33, 0x80, 0x90, 0xF8, 0x6E, 0x82, 0xA3, 0xEB, 0x08, 0x03, 0x3B, 0x80, + 0xDF, 0xF8, 0x10, 0xB2, 0x9B, 0xF8, 0x00, 0x30, 0x33, 0xB1, 0xB0, 0xF8, 0x6C, 0x32, 0x33, 0x80, + 0x90, 0xF8, 0x6E, 0x02, 0x18, 0x1A, 0x38, 0x80, 0xA0, 0x78, 0x68, 0xB1, 0x10, 0xE0, 0x90, 0xF8, + 0x03, 0x43, 0x21, 0x44, 0x90, 0xF8, 0x25, 0x43, 0x09, 0xB2, 0x23, 0x44, 0x90, 0xF8, 0x45, 0x43, + 0x1B, 0xB2, 0x22, 0x44, 0x12, 0xB2, 0xA8, 0xE7, 0x30, 0x88, 0x28, 0x80, 0x38, 0x88, 0x08, 0x80, + 0xE0, 0x78, 0xA1, 0x46, 0x20, 0xB9, 0x30, 0x88, 0xAC, 0xF8, 0x00, 0x00, 0x38, 0x88, 0x10, 0x80, + 0xB2, 0xF9, 0x00, 0x20, 0xB1, 0xF9, 0x00, 0x10, 0xB7, 0xF9, 0x00, 0x00, 0x0A, 0xF0, 0xE4, 0xFF, + 0x6D, 0x4D, 0x00, 0xB2, 0x6D, 0x4A, 0x28, 0x80, 0x31, 0x88, 0x6D, 0x4B, 0x11, 0x80, 0x5D, 0x4C, + 0x39, 0x88, 0x19, 0x80, 0x21, 0x68, 0x91, 0xF8, 0x00, 0xC4, 0x5F, 0xEA, 0xCC, 0x7C, 0x14, 0xD0, + 0x9A, 0xF8, 0x01, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x91, 0xF8, 0x05, 0xC4, 0xB1, 0xF8, + 0x02, 0x84, 0xC4, 0x44, 0xA2, 0xF8, 0x00, 0xC0, 0x91, 0xF8, 0x04, 0x14, 0xAC, 0xEB, 0x01, 0x01, + 0x09, 0xB2, 0x19, 0x80, 0x0A, 0xF0, 0xCE, 0xFF, 0x28, 0x80, 0xB2, 0x46, 0x30, 0x88, 0x5D, 0x4E, + 0x5D, 0x49, 0x5E, 0x4A, 0x30, 0x80, 0x08, 0x80, 0x38, 0x88, 0x10, 0x80, 0x99, 0xF8, 0x04, 0x00, + 0xC8, 0x46, 0x00, 0xB3, 0x20, 0x68, 0xB0, 0xF8, 0x44, 0x34, 0x2B, 0xB1, 0x98, 0xF8, 0x06, 0x30, + 0x13, 0xB1, 0xB0, 0xF8, 0x44, 0x34, 0x04, 0xE0, 0xB0, 0xF8, 0x42, 0x34, 0x13, 0xB1, 0xB0, 0xF8, + 0x42, 0x34, 0x33, 0x80, 0xB0, 0xF8, 0x46, 0x34, 0x33, 0xB1, 0xB0, 0xF8, 0x46, 0x34, 0x0B, 0x80, + 0x90, 0xF8, 0x48, 0x04, 0x18, 0x1A, 0x10, 0x80, 0xB2, 0xF9, 0x00, 0x10, 0xB5, 0xF9, 0x00, 0x00, + 0x0A, 0xF0, 0xA0, 0xFF, 0x28, 0x80, 0x4A, 0x4F, 0xBA, 0xF8, 0x00, 0x00, 0x38, 0x80, 0x98, 0xF8, + 0x05, 0x00, 0x30, 0xB1, 0x20, 0x68, 0xB0, 0xF8, 0x21, 0x14, 0x11, 0xB1, 0xB0, 0xF8, 0x21, 0x04, + 0x38, 0x80, 0x3B, 0x48, 0x43, 0x4D, 0x00, 0x78, 0x18, 0xB1, 0x20, 0x68, 0xB0, 0xF8, 0xBE, 0x02, + 0x19, 0xE0, 0x9B, 0xF8, 0x00, 0x00, 0x00, 0x28, 0xF7, 0xD1, 0x20, 0x68, 0xB0, 0xF9, 0xBC, 0x02, + 0x28, 0x80, 0x98, 0xF8, 0x04, 0x10, 0x21, 0xB1, 0xB6, 0xF9, 0x00, 0x10, 0x0A, 0xF0, 0x7A, 0xFF, + 0x28, 0x80, 0x98, 0xF8, 0x05, 0x00, 0x00, 0x28, 0x06, 0xD0, 0xB7, 0xF9, 0x00, 0x10, 0xB5, 0xF9, + 0x00, 0x00, 0x0A, 0xF0, 0x6F, 0xFF, 0x28, 0x80, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFF, 0x4F, + 0x8A, 0x46, 0x81, 0x46, 0x30, 0x49, 0x0D, 0x98, 0x93, 0x46, 0x4A, 0x0C, 0x04, 0x46, 0x07, 0xE0, + 0x3A, 0xF9, 0x14, 0x30, 0x93, 0x42, 0x00, 0xDA, 0x1A, 0x46, 0x8B, 0x42, 0x00, 0xDD, 0x19, 0x46, + 0x64, 0x1E, 0xF5, 0xD2, 0x00, 0x25, 0x00, 0x29, 0x01, 0xDA, 0x0D, 0x46, 0x02, 0xE0, 0x00, 0x2A, + 0x00, 0xDD, 0x15, 0x46, 0x00, 0x23, 0x1C, 0x46, 0x1E, 0x46, 0x19, 0x46, 0x1F, 0x46, 0x02, 0x46, + 0x12, 0xE0, 0x00, 0xBF, 0x3A, 0xF9, 0x12, 0xC0, 0xAC, 0xEB, 0x05, 0x0C, 0xDC, 0x45, 0x0B, 0xDA, + 0x0C, 0xEB, 0x0B, 0x08, 0xB8, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x02, 0xFB, 0x02, 0x44, 0x02, 0xFB, + 0x0C, 0x11, 0x13, 0x44, 0x66, 0x44, 0x7F, 0x1C, 0x52, 0x1E, 0xEB, 0xD2, 0x04, 0xFB, 0x07, 0xF2, + 0x2C, 0xE0, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x78, 0x12, 0x01, 0x20, 0xCA, 0x06, 0x10, 0x00, + 0x4C, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00, 0x6A, 0x06, 0x10, 0x00, + 0x6C, 0x06, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, 0x70, 0x06, 0x10, 0x00, 0x72, 0x06, 0x10, 0x00, + 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0x74, 0x06, 0x10, 0x00, 0x7C, 0x06, 0x10, 0x00, + 0x7E, 0x06, 0x10, 0x00, 0x84, 0x06, 0x10, 0x00, 0x86, 0x06, 0x10, 0x00, 0x88, 0x06, 0x10, 0x00, + 0x82, 0x06, 0x10, 0x00, 0x76, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x03, 0xFB, 0x13, 0x2E, + 0x01, 0xFB, 0x07, 0xF2, 0x03, 0xFB, 0x16, 0x27, 0x74, 0x43, 0x01, 0xFB, 0x13, 0x46, 0x00, 0x24, + 0x21, 0x46, 0x02, 0x46, 0x25, 0xE0, 0x00, 0x23, 0xBE, 0xF1, 0x00, 0x0F, 0x0F, 0xD0, 0x07, 0xFB, + 0x02, 0x6C, 0x9C, 0xFB, 0xFE, 0xF3, 0xDC, 0x46, 0x5B, 0x45, 0x01, 0xDD, 0x63, 0x46, 0x06, 0xE0, + 0xDD, 0xF8, 0x0C, 0xC0, 0x13, 0xEB, 0x0C, 0x0F, 0x01, 0xD5, 0x03, 0x9B, 0x5B, 0x42, 0x3A, 0xF8, + 0x12, 0xC0, 0x2B, 0x44, 0xAC, 0xEB, 0x03, 0x03, 0xDD, 0xF8, 0x0C, 0xC0, 0x1B, 0xB2, 0x63, 0x45, + 0x05, 0xDA, 0x9C, 0x44, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xDD, 0x1C, 0x44, 0x49, 0x1C, 0x29, 0xF8, + 0x12, 0x30, 0x52, 0x1E, 0xD7, 0xD2, 0x01, 0xB9, 0x01, 0x21, 0x94, 0xFB, 0xF1, 0xF1, 0x04, 0xE0, + 0x39, 0xF8, 0x10, 0x20, 0x52, 0x1A, 0x29, 0xF8, 0x10, 0x20, 0x40, 0x1E, 0xF8, 0xD2, 0xBD, 0xE8, + 0xFF, 0x8F, 0x2D, 0xE9, 0xF8, 0x43, 0x1F, 0x46, 0xFE, 0x4B, 0x0E, 0x46, 0x05, 0x46, 0x1B, 0x68, + 0x14, 0x46, 0xB3, 0xF9, 0xDA, 0x92, 0xB3, 0xF9, 0xDC, 0x82, 0x0A, 0xE0, 0x43, 0x46, 0x4A, 0x46, + 0x31, 0x46, 0x28, 0x46, 0x00, 0x97, 0xFF, 0xF7, 0x41, 0xFF, 0x06, 0xEB, 0x47, 0x06, 0x05, 0xEB, + 0x47, 0x05, 0x64, 0x1E, 0xF2, 0xD2, 0xBD, 0xE8, 0xF8, 0x83, 0x2D, 0xE9, 0xFF, 0x5F, 0xF2, 0x4C, + 0x88, 0x46, 0x00, 0x26, 0x07, 0x46, 0x92, 0x46, 0x35, 0x46, 0x4F, 0xF4, 0x66, 0x71, 0x40, 0x46, + 0x26, 0x60, 0x10, 0xF0, 0xE6, 0xF9, 0x00, 0x21, 0x40, 0x46, 0x10, 0xF0, 0xF9, 0xFA, 0x81, 0x46, + 0x00, 0x21, 0x38, 0x46, 0x10, 0xF0, 0xEC, 0xFA, 0x00, 0x22, 0xE8, 0x4B, 0xE8, 0x4F, 0x29, 0xE0, + 0x00, 0x21, 0x4F, 0xF0, 0x01, 0x0E, 0xDF, 0xF8, 0x8C, 0xB3, 0x18, 0xE0, 0x30, 0xF9, 0x11, 0x80, + 0xD0, 0x45, 0x05, 0xDD, 0x09, 0xF8, 0x01, 0xE0, 0x30, 0xF9, 0x11, 0xC0, 0x76, 0x1C, 0x65, 0x44, + 0xDB, 0xF8, 0x00, 0xC0, 0x30, 0xF9, 0x11, 0x80, 0xBC, 0xF8, 0x55, 0xC3, 0xE0, 0x45, 0x05, 0xDD, + 0xD4, 0xF8, 0x00, 0xC0, 0x0C, 0xF1, 0x01, 0x0C, 0xC4, 0xF8, 0x00, 0xC0, 0x49, 0x1C, 0x93, 0xF8, + 0x00, 0xC0, 0x61, 0x45, 0xE2, 0xDB, 0x0C, 0xF0, 0xFF, 0x01, 0x09, 0xF1, 0x28, 0x09, 0x00, 0xEB, + 0x41, 0x00, 0x52, 0x1C, 0x39, 0x78, 0x8A, 0x42, 0xD2, 0xDB, 0x03, 0x98, 0x05, 0x60, 0x30, 0x46, + 0x04, 0xB0, 0xE9, 0xE6, 0x06, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x12, 0x30, 0x8B, 0x42, 0x01, 0xDD, + 0x01, 0x20, 0x70, 0x47, 0x52, 0x1E, 0xF7, 0xD2, 0x00, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xFC, 0x47, + 0x04, 0x46, 0xC8, 0x48, 0xC8, 0x4F, 0x13, 0x46, 0x02, 0x68, 0x38, 0x68, 0xFF, 0xF7, 0xC3, 0xFD, + 0x03, 0x20, 0x0E, 0xF0, 0x20, 0xF9, 0xDF, 0xF8, 0xFC, 0x92, 0xDF, 0xF8, 0x10, 0x83, 0xBF, 0x4D, + 0xD9, 0xF8, 0x00, 0x00, 0xBE, 0x4E, 0x90, 0xF8, 0xAA, 0x02, 0x80, 0x07, 0x15, 0xD5, 0xC0, 0x48, + 0xB0, 0xF9, 0x00, 0x20, 0xBF, 0x48, 0xB0, 0xF9, 0x00, 0x10, 0xBF, 0x48, 0xB0, 0xF9, 0x00, 0x00, + 0x0A, 0xF0, 0x1A, 0xFE, 0x03, 0xB2, 0x29, 0x78, 0x30, 0x78, 0xCD, 0xE9, 0x00, 0x01, 0x39, 0x68, + 0xD8, 0xF8, 0x00, 0x20, 0x08, 0x46, 0x00, 0xF0, 0xF6, 0xFA, 0xB8, 0x48, 0xD8, 0xF8, 0x00, 0x20, + 0x39, 0x68, 0xB0, 0xF9, 0x00, 0x30, 0x20, 0x46, 0x0B, 0xF0, 0x97, 0xFC, 0x03, 0x20, 0x0E, 0xF0, + 0x0D, 0xF9, 0xD9, 0xF8, 0x00, 0x00, 0x4F, 0x46, 0x90, 0xF8, 0xAA, 0x02, 0x00, 0x06, 0x05, 0xD5, + 0x21, 0x46, 0x2B, 0x78, 0x32, 0x78, 0x08, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0x38, 0x68, 0x90, 0xF8, + 0xAA, 0x02, 0x40, 0x07, 0x25, 0xD5, 0x30, 0x78, 0x2E, 0x78, 0x32, 0x46, 0x1F, 0xE0, 0x00, 0x21, + 0x03, 0x46, 0x0C, 0xE0, 0x03, 0xFB, 0x06, 0x27, 0x34, 0xF9, 0x17, 0x50, 0x00, 0x2D, 0x04, 0xDD, + 0x09, 0xB1, 0x8D, 0x42, 0x03, 0xDA, 0x29, 0x46, 0x01, 0xE0, 0x00, 0x21, 0x43, 0x1C, 0x5B, 0x1E, + 0xF0, 0xD2, 0x00, 0x29, 0x0B, 0xDD, 0x03, 0x46, 0x07, 0xE0, 0x00, 0xBF, 0x03, 0xFB, 0x06, 0x25, + 0x34, 0xF8, 0x15, 0x70, 0x7F, 0x1A, 0x24, 0xF8, 0x15, 0x70, 0x5B, 0x1E, 0xF6, 0xD2, 0x52, 0x1E, + 0xDD, 0xD2, 0xBD, 0xE8, 0xFC, 0x87, 0x2D, 0xE9, 0xF0, 0x43, 0x91, 0x46, 0x1C, 0x46, 0x36, 0xE0, + 0x93, 0x4D, 0x4F, 0xF0, 0x01, 0x0C, 0x6A, 0x0C, 0xE0, 0x46, 0x4F, 0x46, 0x12, 0xE0, 0x00, 0xBF, + 0x07, 0xFB, 0x03, 0x46, 0x31, 0xF9, 0x16, 0x60, 0x96, 0x42, 0x00, 0xDA, 0x32, 0x46, 0xAE, 0x42, + 0x00, 0xDD, 0x35, 0x46, 0x00, 0x2E, 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x08, 0x02, 0xE0, 0x01, 0xDA, + 0x4F, 0xF0, 0x00, 0x0C, 0x7F, 0x1E, 0xEB, 0xD2, 0xBC, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0xB8, 0xF1, + 0x00, 0x0F, 0x14, 0xD1, 0x5C, 0xEA, 0x08, 0x06, 0x11, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, 0x03, 0xD1, + 0xB8, 0xF1, 0x00, 0x0F, 0x00, 0xD0, 0x2A, 0x46, 0x4E, 0x46, 0x06, 0xE0, 0x06, 0xFB, 0x03, 0x45, + 0x31, 0xF8, 0x15, 0x70, 0xBF, 0x1A, 0x20, 0xF8, 0x15, 0x70, 0x76, 0x1E, 0xF6, 0xD2, 0x64, 0x1E, + 0xC6, 0xD2, 0xBD, 0xE8, 0xF0, 0x83, 0x2D, 0xE9, 0xF3, 0x4F, 0x76, 0x49, 0x89, 0xB0, 0x09, 0x78, + 0x00, 0x29, 0x75, 0xD1, 0xCD, 0xE9, 0x00, 0x10, 0x68, 0x48, 0x07, 0x91, 0x8A, 0x46, 0x90, 0xF8, + 0x00, 0x90, 0x67, 0x48, 0x88, 0x46, 0x00, 0x78, 0x08, 0x90, 0x57, 0xE0, 0xDF, 0xF8, 0xB0, 0xB1, + 0x00, 0x20, 0xCD, 0xE9, 0x05, 0x0B, 0x05, 0x46, 0x04, 0x90, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x10, 0xF0, 0x11, 0xF8, 0x0A, 0x9A, 0xD2, 0xE9, 0x00, 0x32, 0x03, 0x40, 0x0A, 0x40, 0xCD, 0xE9, + 0x02, 0x23, 0x22, 0xE0, 0x01, 0x98, 0x30, 0xF9, 0x15, 0x40, 0x5C, 0x45, 0x00, 0xDD, 0xA3, 0x46, + 0x05, 0x98, 0x84, 0x42, 0x00, 0xDA, 0x05, 0x94, 0xDD, 0xE9, 0x02, 0x10, 0x08, 0x43, 0x13, 0xD1, + 0x0A, 0x98, 0x2A, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x02, 0x67, 0x01, 0x20, 0x0F, 0xF0, 0xF3, 0xFF, + 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x07, 0xD1, 0x06, 0x98, 0x84, 0x42, 0x00, 0xDD, 0x06, 0x94, + 0x04, 0x98, 0x84, 0x42, 0x00, 0xDA, 0x04, 0x94, 0x6D, 0x1C, 0x4D, 0x45, 0xDA, 0xDB, 0x05, 0x98, + 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0xAB, 0xEB, 0x00, 0x00, 0x01, 0xB2, 0x04, 0x98, 0x00, 0x28, + 0x00, 0xDA, 0x40, 0x42, 0x06, 0x9A, 0x10, 0x1A, 0x02, 0xB2, 0x51, 0x45, 0x00, 0xDD, 0x8A, 0x46, + 0xDD, 0xE9, 0x02, 0x10, 0x08, 0x43, 0x03, 0xD1, 0x00, 0x98, 0x82, 0x42, 0x00, 0xDA, 0x00, 0x92, + 0x01, 0x99, 0x08, 0xF1, 0x01, 0x08, 0x01, 0xEB, 0x49, 0x00, 0x01, 0x90, 0x08, 0x99, 0x88, 0x45, + 0xA4, 0xDB, 0x34, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0xC0, 0x22, 0xB0, 0xF9, 0xC2, 0x12, 0x92, 0x45, + 0x07, 0xDD, 0x00, 0x9A, 0x49, 0x42, 0x8A, 0x42, 0x03, 0xDA, 0x01, 0x21, 0x07, 0x91, 0x03, 0xE0, + 0x18, 0xE0, 0x38, 0x49, 0x00, 0x22, 0x4A, 0x70, 0x90, 0xF8, 0xC4, 0x12, 0x35, 0x48, 0x07, 0x9A, + 0x40, 0x1C, 0x0A, 0xF0, 0x98, 0xFD, 0x33, 0x49, 0x08, 0x70, 0x28, 0xB1, 0xFF, 0xF7, 0x94, 0xFC, + 0x01, 0x21, 0x08, 0x20, 0x0A, 0xF0, 0x4E, 0xF8, 0x2F, 0x48, 0xA0, 0xF8, 0x40, 0xA0, 0x00, 0x99, + 0xA0, 0xF8, 0x42, 0x10, 0x2B, 0x48, 0x02, 0x78, 0x2B, 0x48, 0x01, 0x7C, 0x62, 0xF3, 0xC7, 0x11, + 0x01, 0x74, 0x0B, 0xB0, 0x6F, 0xE4, 0x2D, 0xE9, 0xF7, 0x4F, 0x93, 0x46, 0x27, 0x4A, 0x4F, 0xF0, + 0x00, 0x09, 0x06, 0x46, 0x15, 0x78, 0x82, 0xF8, 0x00, 0x90, 0xFF, 0xF7, 0x75, 0xFC, 0x21, 0x48, + 0x02, 0x21, 0x00, 0x1D, 0x08, 0xF0, 0x3E, 0xF8, 0x21, 0x48, 0x1E, 0x4C, 0x2A, 0x46, 0x00, 0x78, + 0x31, 0x46, 0x01, 0x28, 0x60, 0x68, 0x5B, 0xD0, 0xFF, 0xF7, 0x90, 0xFE, 0x0D, 0x4D, 0xDF, 0xF8, + 0x3C, 0x80, 0x0F, 0x4E, 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x80, 0x07, 0x06, 0xD5, 0x61, 0x68, + 0x98, 0xF8, 0x00, 0x30, 0x32, 0x78, 0x08, 0x46, 0xFF, 0xF7, 0xF5, 0xFE, 0x29, 0x68, 0x0F, 0x4F, + 0x91, 0xF8, 0xAA, 0x02, 0x02, 0x07, 0x26, 0xD4, 0xC0, 0x06, 0x24, 0xD4, 0x91, 0xF8, 0xAB, 0x02, + 0xC0, 0x07, 0x1F, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x5C, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, + 0xB9, 0x06, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, 0xE4, 0x06, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, + 0x6C, 0x06, 0x10, 0x00, 0x6A, 0x06, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, + 0x00, 0x80, 0xFF, 0xFF, 0x28, 0x05, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x50, 0x07, 0x10, 0x00, + 0xBF, 0x06, 0x10, 0x00, 0x06, 0xD0, 0x61, 0x68, 0xB7, 0xF9, 0x00, 0x30, 0xF8, 0x4A, 0x08, 0x46, + 0xFF, 0xF7, 0x13, 0xFC, 0xB7, 0xF9, 0x00, 0x00, 0x61, 0x68, 0x42, 0x00, 0xF5, 0x48, 0x00, 0x68, + 0x0F, 0xF0, 0x60, 0xFF, 0x98, 0xF8, 0x00, 0x20, 0x31, 0x78, 0x60, 0x68, 0xFF, 0xF7, 0xC0, 0xFA, + 0xDF, 0xF8, 0xC4, 0x83, 0xDF, 0xF8, 0xC4, 0xA3, 0x98, 0xF8, 0x00, 0x00, 0x30, 0xB9, 0x02, 0xE0, + 0xFF, 0xF7, 0x46, 0xF9, 0xA2, 0xE7, 0x98, 0xF8, 0x01, 0x00, 0x28, 0xB1, 0x59, 0x46, 0x62, 0x68, + 0x01, 0x98, 0xFE, 0xF7, 0x95, 0xFD, 0x01, 0xE0, 0x8A, 0xF8, 0x00, 0x90, 0xE8, 0x48, 0xE9, 0x4E, + 0x40, 0x78, 0x02, 0x28, 0x28, 0x68, 0x90, 0xF8, 0xAA, 0x12, 0x4F, 0xEA, 0x81, 0x61, 0x16, 0xD3, + 0x00, 0x29, 0x07, 0xDA, 0x61, 0x68, 0xB0, 0xF9, 0xBA, 0x22, 0xB7, 0xF9, 0x00, 0x30, 0x08, 0x46, + 0x00, 0xF0, 0xA9, 0xF9, 0x28, 0x68, 0x90, 0xF8, 0xAA, 0x12, 0x49, 0x06, 0x12, 0xD5, 0xB0, 0xF9, + 0xB8, 0x32, 0xDD, 0x4A, 0x61, 0x68, 0x30, 0x68, 0x06, 0xF0, 0x70, 0xFB, 0x11, 0xE0, 0x00, 0x29, + 0x08, 0xDA, 0xB0, 0xF9, 0xBA, 0x22, 0xB7, 0xF9, 0x00, 0x30, 0x61, 0x68, 0x30, 0x68, 0x00, 0xF0, + 0x92, 0xF9, 0x06, 0xE0, 0xB7, 0xF9, 0x00, 0x00, 0x61, 0x68, 0x42, 0x00, 0x30, 0x68, 0x0F, 0xF0, + 0x11, 0xFF, 0x02, 0x21, 0xD1, 0x48, 0x07, 0xF0, 0xF8, 0xFF, 0x9A, 0xF8, 0x00, 0x00, 0x4F, 0xF0, + 0x01, 0x0B, 0xA8, 0xB1, 0x98, 0xF8, 0x00, 0x00, 0x90, 0xB1, 0xCD, 0x48, 0x00, 0x78, 0x01, 0x28, + 0x0E, 0xD1, 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x40, 0x07, 0x24, 0xD5, 0x20, 0x78, 0x60, 0xB9, + 0x84, 0xF8, 0x00, 0xB0, 0xFF, 0xF7, 0xB0, 0xFB, 0x01, 0x21, 0x08, 0x20, 0x09, 0xF0, 0x6A, 0xFF, + 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x40, 0x07, 0x12, 0xD5, 0xC2, 0x49, 0x30, 0x68, 0xFF, 0xF7, + 0x82, 0xFE, 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x12, 0x09, 0x07, 0x09, 0xD5, 0x21, 0x78, 0x39, 0xB1, + 0xB0, 0xF9, 0xC5, 0x32, 0xB3, 0x48, 0xB8, 0x4A, 0x01, 0x68, 0x30, 0x68, 0x06, 0xF0, 0x26, 0xFB, + 0x9A, 0xF8, 0x00, 0x00, 0x30, 0xB1, 0x98, 0xF8, 0x01, 0x00, 0x18, 0xB1, 0xB4, 0x48, 0x00, 0x78, + 0x02, 0x28, 0x1C, 0xD0, 0xB4, 0x48, 0xB7, 0xF9, 0x00, 0x20, 0xB0, 0xF9, 0x00, 0x10, 0x30, 0x68, + 0xFF, 0xF7, 0xA0, 0xFD, 0xB1, 0x49, 0xB2, 0x4D, 0xA0, 0xB1, 0x81, 0xF8, 0x00, 0xB0, 0x02, 0x24, + 0x01, 0x21, 0xB0, 0x48, 0x07, 0xF0, 0x46, 0xFF, 0xB0, 0x48, 0xAF, 0x4B, 0xB0, 0xF9, 0x00, 0x20, + 0xAC, 0x48, 0x01, 0x68, 0x30, 0x68, 0xFF, 0xF7, 0x40, 0xFD, 0x28, 0x60, 0x0D, 0xE0, 0x04, 0x20, + 0xBD, 0xE8, 0xFE, 0x8F, 0xAA, 0x4A, 0xC5, 0xF8, 0x00, 0x90, 0x01, 0x24, 0xC2, 0xF8, 0x00, 0x90, + 0xA5, 0x4A, 0xC2, 0xF8, 0x00, 0x90, 0x81, 0xF8, 0x00, 0x90, 0x20, 0x46, 0xF0, 0xE7, 0x2D, 0xE9, + 0xF0, 0x41, 0x07, 0x46, 0xA3, 0x48, 0x00, 0x26, 0x05, 0x78, 0x06, 0x70, 0xFF, 0xF7, 0x54, 0xFB, + 0x02, 0x21, 0x96, 0x48, 0x07, 0xF0, 0x1E, 0xFF, 0x9F, 0x48, 0x94, 0x4C, 0x2A, 0x46, 0x00, 0x78, + 0x24, 0x1F, 0x01, 0x28, 0x60, 0x68, 0x39, 0x46, 0x4B, 0xD0, 0xFF, 0xF7, 0x6F, 0xFD, 0x9B, 0x4D, + 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x80, 0x07, 0x07, 0xD5, 0x99, 0x48, 0x61, 0x68, 0x03, 0x78, + 0x98, 0x48, 0x02, 0x78, 0x08, 0x46, 0xFF, 0xF7, 0xD6, 0xFD, 0x29, 0x68, 0x96, 0x4D, 0x91, 0xF8, + 0xAA, 0x02, 0x02, 0x07, 0x05, 0xD4, 0xC0, 0x06, 0x03, 0xD4, 0x91, 0xF8, 0xAB, 0x02, 0xC0, 0x07, + 0x06, 0xD0, 0x61, 0x68, 0xB5, 0xF9, 0x00, 0x30, 0x79, 0x4A, 0x08, 0x46, 0xFF, 0xF7, 0x15, 0xFB, + 0x61, 0x68, 0xB5, 0xF9, 0x00, 0x00, 0x7B, 0x4C, 0x42, 0x00, 0x20, 0x68, 0x0F, 0xF0, 0x62, 0xFE, + 0x02, 0x21, 0x7A, 0x48, 0x07, 0xF0, 0x49, 0xFF, 0x7B, 0x48, 0xB5, 0xF9, 0x00, 0x20, 0xB0, 0xF9, + 0x00, 0x10, 0x20, 0x68, 0xFF, 0xF7, 0x2E, 0xFD, 0x78, 0x49, 0xA8, 0xB1, 0x01, 0x20, 0x08, 0x70, + 0x01, 0x46, 0x02, 0x25, 0x77, 0x48, 0x07, 0xF0, 0xD5, 0xFE, 0x78, 0x48, 0x76, 0x4B, 0xB0, 0xF9, + 0x00, 0x20, 0x74, 0x48, 0x01, 0x68, 0x20, 0x68, 0xFF, 0xF7, 0xCF, 0xFC, 0x70, 0x49, 0x08, 0x60, + 0x04, 0xE0, 0xFF, 0xF7, 0x35, 0xF8, 0xB2, 0xE7, 0x0E, 0x70, 0x01, 0x25, 0x28, 0x46, 0xBD, 0xE8, + 0xF0, 0x81, 0x66, 0x49, 0x10, 0xB5, 0x09, 0x1F, 0x68, 0x4A, 0x00, 0x20, 0x48, 0x60, 0x10, 0x70, + 0x08, 0x70, 0x48, 0x70, 0xFF, 0xF7, 0x9C, 0xF8, 0xFF, 0xF7, 0x8B, 0xF9, 0xBD, 0xE8, 0x10, 0x40, + 0x00, 0xF0, 0x02, 0xB8, 0xFF, 0xF7, 0x26, 0xBA, 0x68, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x6B, 0x49, + 0x6B, 0x4B, 0xB0, 0xF8, 0x00, 0x23, 0x0A, 0x80, 0xB0, 0xF8, 0x22, 0x13, 0x69, 0x4C, 0x19, 0x80, + 0xB0, 0xF8, 0x42, 0x33, 0x23, 0x80, 0x68, 0x4C, 0x22, 0x80, 0x68, 0x4A, 0x11, 0x80, 0x68, 0x49, + 0x0B, 0x80, 0x5A, 0x49, 0xB0, 0xF8, 0xBC, 0x02, 0x08, 0x80, 0x10, 0xBD, 0x4C, 0x48, 0x00, 0x22, + 0x43, 0x78, 0x4E, 0x48, 0x00, 0x1F, 0x02, 0x2B, 0x01, 0x78, 0x47, 0x48, 0x00, 0xD2, 0x21, 0xB1, + 0x82, 0x70, 0x02, 0x2B, 0x00, 0xD2, 0x01, 0xB1, 0xC2, 0x70, 0x83, 0x79, 0x0B, 0x43, 0x01, 0xD0, + 0x02, 0x71, 0x42, 0x71, 0x70, 0x47, 0x2D, 0xE9, 0xFF, 0x4F, 0x9B, 0x46, 0xDD, 0xE9, 0x0D, 0x19, + 0x86, 0x46, 0x64, 0xE0, 0x01, 0x9A, 0x01, 0xFB, 0x09, 0xF0, 0x02, 0xEB, 0x40, 0x04, 0x02, 0x9A, + 0x54, 0x4F, 0x02, 0xEB, 0x40, 0x06, 0x4F, 0xF0, 0x01, 0x0C, 0x0E, 0xEB, 0x40, 0x05, 0x7B, 0x0C, + 0xE2, 0x46, 0x4A, 0x46, 0x15, 0xE0, 0x00, 0xBF, 0x36, 0xF8, 0x12, 0x00, 0x34, 0xF8, 0x12, 0x80, + 0xA0, 0xEB, 0x08, 0x00, 0x00, 0xB2, 0x98, 0x42, 0x00, 0xDA, 0x03, 0x46, 0xB8, 0x42, 0x00, 0xDD, + 0x07, 0x46, 0x00, 0x28, 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x0A, 0x02, 0xE0, 0x01, 0xDA, 0x4F, 0xF0, + 0x00, 0x0C, 0x52, 0x1E, 0xE8, 0xD2, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0xBA, 0xF1, 0x00, 0x0F, + 0x01, 0xD0, 0x00, 0x20, 0x0B, 0xE0, 0x5C, 0xEA, 0x0A, 0x00, 0x08, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, + 0x04, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x38, 0x46, 0x00, 0xE0, 0x18, 0x46, 0x00, 0x27, + 0x3B, 0x46, 0x4A, 0x46, 0xCB, 0xF1, 0x00, 0x0A, 0x10, 0xE0, 0x00, 0xBF, 0x36, 0xF8, 0x12, 0xC0, + 0x34, 0xF8, 0x12, 0x80, 0xAC, 0xEB, 0x08, 0x0C, 0xAC, 0xEB, 0x00, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC, + 0xDC, 0x45, 0x03, 0xDA, 0xD4, 0x45, 0x01, 0xDD, 0x67, 0x44, 0x5B, 0x1C, 0x52, 0x1E, 0xED, 0xD2, + 0x03, 0xB9, 0x01, 0x23, 0x97, 0xFB, 0xF3, 0xF2, 0x02, 0x44, 0x48, 0x46, 0x05, 0xE0, 0x00, 0xBF, + 0x34, 0xF8, 0x10, 0x30, 0x13, 0x44, 0x25, 0xF8, 0x10, 0x30, 0x40, 0x1E, 0xF8, 0xD2, 0x49, 0x1E, + 0x98, 0xD2, 0xBD, 0xE8, 0xFF, 0x8F, 0x70, 0xB5, 0x00, 0x24, 0x26, 0x46, 0x47, 0xE0, 0x00, 0xBF, + 0x31, 0xF9, 0x14, 0x50, 0x95, 0x42, 0x3F, 0xDA, 0x20, 0xF8, 0x14, 0x60, 0x3E, 0xE0, 0x00, 0x00, + 0x78, 0x12, 0x01, 0x20, 0xE0, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x0C, 0x05, 0x10, 0x00, + 0x4C, 0x07, 0x10, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x2A, 0x6C, 0x01, 0x00, 0x2C, 0x05, 0x10, 0x00, + 0x0E, 0x05, 0x10, 0x00, 0x80, 0x24, 0x10, 0x00, 0x74, 0x06, 0x10, 0x00, 0xC1, 0x06, 0x10, 0x00, + 0x58, 0x06, 0x10, 0x00, 0x2C, 0x06, 0x10, 0x00, 0x60, 0x06, 0x10, 0x00, 0x76, 0x06, 0x10, 0x00, + 0x5C, 0x06, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, 0xBF, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00, + 0x6A, 0x06, 0x10, 0x00, 0x6C, 0x06, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, 0x70, 0x06, 0x10, 0x00, + 0x72, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x20, 0xF8, 0x14, 0x50, 0x64, 0x1C, 0x9C, 0x42, + 0xB6, 0xDB, 0x70, 0xBD, 0x7F, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x80, 0x70, 0x47, 0x30, 0xB5, + 0x7D, 0x49, 0x02, 0x46, 0x01, 0x20, 0x0C, 0x68, 0x94, 0xF8, 0xC6, 0x39, 0x4B, 0xB1, 0x79, 0x4D, + 0xB2, 0xF8, 0x44, 0x10, 0x6D, 0x68, 0x49, 0x1B, 0x00, 0xD5, 0x49, 0x42, 0x8B, 0x42, 0x00, 0xDA, + 0x00, 0x20, 0x94, 0xF8, 0xC7, 0x19, 0x00, 0x29, 0x12, 0xD0, 0x72, 0x4C, 0xB2, 0xF9, 0x1A, 0x50, + 0x08, 0x34, 0xB2, 0xF9, 0x18, 0x20, 0xB4, 0xF9, 0x02, 0x30, 0xB4, 0xF9, 0x00, 0x40, 0x5B, 0x1B, + 0xA2, 0x1A, 0x5B, 0x43, 0x02, 0xFB, 0x02, 0x32, 0x49, 0x43, 0x8A, 0x42, 0x00, 0xDD, 0x00, 0x20, + 0x30, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x68, 0x4F, 0xDF, 0xF8, 0x98, 0x81, 0x06, 0x00, 0x4F, 0xF0, + 0x05, 0x04, 0x4F, 0xF0, 0x06, 0x05, 0x10, 0xD0, 0x96, 0xF8, 0x3E, 0x01, 0x00, 0xF0, 0x74, 0xF9, + 0x04, 0x46, 0x38, 0x68, 0x90, 0xF8, 0xC5, 0x09, 0x18, 0xB1, 0xB6, 0xF8, 0x44, 0x10, 0x81, 0x42, + 0x2B, 0xD8, 0xB0, 0x69, 0x00, 0xF0, 0x8A, 0xF8, 0x38, 0xB3, 0x98, 0xF8, 0x00, 0x00, 0x4F, 0xF0, + 0x00, 0x09, 0x07, 0x28, 0x0E, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x04, 0x04, 0x23, 0x3B, 0x54, 0x04, + 0x04, 0x00, 0x05, 0x2C, 0x04, 0xD0, 0x04, 0x2C, 0x06, 0xD0, 0x01, 0x2C, 0x06, 0xD0, 0x14, 0xE0, + 0x88, 0xF8, 0x00, 0x90, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x20, 0x51, 0xE0, 0xFF, 0xF7, 0x9A, 0xFF, + 0x02, 0x20, 0x88, 0xF8, 0x00, 0x00, 0xA8, 0xF8, 0x02, 0x90, 0xB6, 0xF8, 0x44, 0x00, 0xC8, 0xF8, + 0x04, 0x00, 0xB0, 0x69, 0xC8, 0xF8, 0x08, 0x00, 0xEC, 0xE7, 0x88, 0xF8, 0x00, 0x50, 0xE9, 0xE7, + 0xB8, 0xF8, 0x02, 0x00, 0x40, 0x1C, 0x80, 0xB2, 0xA8, 0xF8, 0x02, 0x00, 0x03, 0x2C, 0x03, 0xD0, + 0x39, 0x68, 0x91, 0xF8, 0xC0, 0x19, 0x2F, 0xE0, 0x03, 0x20, 0x88, 0xF8, 0x00, 0x00, 0xA8, 0xF8, + 0x02, 0x90, 0xD7, 0xE7, 0x05, 0x2C, 0xD5, 0xD0, 0x30, 0x46, 0xFF, 0xF7, 0x78, 0xFF, 0x15, 0xE0, + 0xB8, 0xF8, 0x02, 0x10, 0x49, 0x1C, 0x89, 0xB2, 0xA8, 0xF8, 0x02, 0x10, 0x01, 0x2C, 0x05, 0xD0, + 0x38, 0x68, 0x90, 0xF8, 0xC1, 0x29, 0x8A, 0x42, 0xD7, 0xD9, 0xC3, 0xE7, 0x30, 0x46, 0xFF, 0xF7, + 0x66, 0xFF, 0x04, 0x22, 0x88, 0xF8, 0x00, 0x20, 0xA8, 0xF8, 0x02, 0x90, 0x00, 0x28, 0xCC, 0xD0, + 0xB8, 0xE7, 0xB8, 0xF8, 0x02, 0x00, 0x40, 0x1C, 0x80, 0xB2, 0xA8, 0xF8, 0x02, 0x00, 0x03, 0x2C, + 0x05, 0xD0, 0x39, 0x68, 0x91, 0xF8, 0xC2, 0x19, 0x81, 0x42, 0xD3, 0xD8, 0xBD, 0xE7, 0x05, 0x20, + 0x88, 0xF8, 0x00, 0x00, 0xA6, 0xE7, 0x38, 0xB5, 0x00, 0x21, 0x00, 0x91, 0x69, 0x46, 0x00, 0xF0, + 0xCE, 0xF8, 0x20, 0x4C, 0x01, 0x28, 0x02, 0xD9, 0x06, 0x20, 0x20, 0x70, 0x05, 0xE0, 0x00, 0x98, + 0xFF, 0xF7, 0x67, 0xFF, 0x20, 0x78, 0x05, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x38, 0xBD, 0x1B, 0x48, + 0x01, 0x21, 0x41, 0x70, 0x05, 0x21, 0x81, 0x70, 0x01, 0x20, 0x38, 0xBD, 0xF0, 0xB5, 0x16, 0x49, + 0x04, 0x46, 0x01, 0x20, 0x0A, 0x68, 0x92, 0xF8, 0xC3, 0x19, 0x92, 0xF8, 0xC3, 0x39, 0x8E, 0x00, + 0x92, 0xF8, 0xC4, 0x19, 0x8D, 0x00, 0x92, 0xF8, 0x36, 0x10, 0xCF, 0x07, 0x51, 0x8E, 0xA1, 0xEB, + 0x83, 0x01, 0x93, 0x8E, 0x92, 0xF8, 0xC4, 0x29, 0x09, 0xB2, 0xA3, 0xEB, 0x82, 0x02, 0x12, 0xB2, + 0x0C, 0xD0, 0x13, 0x46, 0x22, 0x14, 0xB2, 0x42, 0x06, 0xDB, 0x9A, 0x42, 0x04, 0xDC, 0x22, 0xB2, + 0xAA, 0x42, 0x01, 0xDB, 0x8A, 0x42, 0x00, 0xDD, 0x00, 0x20, 0xF0, 0xBD, 0x0B, 0x46, 0x11, 0x46, + 0xF0, 0xE7, 0x00, 0x00, 0x30, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xA0, 0x24, 0x10, 0x00, + 0x75, 0x48, 0x90, 0xF8, 0x2C, 0x00, 0x06, 0x28, 0x01, 0xD0, 0x05, 0x28, 0x07, 0xD1, 0x73, 0x48, + 0x73, 0x49, 0x00, 0x68, 0x90, 0xF8, 0xB4, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x08, 0x60, 0x71, 0x49, + 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0xB8, 0x81, 0x04, 0x46, + 0x98, 0xF8, 0x00, 0x00, 0x10, 0xB9, 0x0A, 0x21, 0x88, 0xF8, 0x00, 0x10, 0x00, 0x27, 0x04, 0xF5, + 0x80, 0x56, 0x01, 0x25, 0xD6, 0xF8, 0xB0, 0x03, 0x05, 0xFA, 0x07, 0xF1, 0x08, 0x42, 0x0C, 0xD0, + 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x04, 0xEB, 0x01, 0x11, 0x91, 0xF8, 0x3E, 0x01, + 0x03, 0x28, 0x02, 0xD1, 0x20, 0x46, 0x03, 0xF0, 0x83, 0xF9, 0x7F, 0x1C, 0xFF, 0xB2, 0x0F, 0x2F, + 0xE8, 0xD3, 0x00, 0x26, 0x04, 0xF5, 0x80, 0x57, 0x05, 0xFA, 0x06, 0xF1, 0xD7, 0xF8, 0xB0, 0x03, + 0x08, 0x42, 0x0A, 0xD0, 0xC6, 0xEB, 0xC6, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x04, 0xEB, 0x01, 0x10, + 0x00, 0xF1, 0x18, 0x01, 0x0C, 0x30, 0x0A, 0xF0, 0x48, 0xFA, 0x76, 0x1C, 0xF6, 0xB2, 0x0F, 0x2E, + 0xEA, 0xD3, 0x51, 0x48, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x98, 0xF8, 0x08, 0x00, 0x80, 0x06, + 0x08, 0xD5, 0x20, 0x46, 0xFF, 0xF7, 0x57, 0xFF, 0x20, 0xB1, 0x4B, 0x48, 0x09, 0xF0, 0x55, 0xFC, + 0xFF, 0xF7, 0x98, 0xFE, 0x00, 0x27, 0xA8, 0x46, 0x04, 0xF5, 0x80, 0x56, 0x08, 0xFA, 0x07, 0xF0, + 0xD6, 0xF8, 0xB0, 0x13, 0x01, 0x42, 0x11, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x01, + 0x04, 0xEB, 0x01, 0x15, 0x95, 0xF8, 0x3E, 0x01, 0x08, 0x28, 0x07, 0xD1, 0x29, 0x46, 0x20, 0x46, + 0x03, 0xF0, 0x59, 0xF9, 0x29, 0x46, 0x20, 0x46, 0x03, 0xF0, 0x1C, 0xF9, 0x7F, 0x1C, 0xFF, 0xB2, + 0x0F, 0x2F, 0xE3, 0xD3, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0xF0, 0x38, 0xB8, 0x30, 0xB5, + 0x05, 0x46, 0x00, 0x20, 0x4F, 0xEA, 0x00, 0x03, 0xC3, 0xEB, 0xC3, 0x02, 0x02, 0xEB, 0x42, 0x02, + 0x05, 0xEB, 0x02, 0x14, 0x94, 0xF8, 0x3E, 0x21, 0x01, 0x2A, 0x0D, 0xD0, 0x02, 0x2A, 0x0B, 0xD0, + 0x03, 0x2A, 0x09, 0xD0, 0x04, 0x2A, 0x07, 0xD0, 0x05, 0x2A, 0x05, 0xD0, 0x06, 0x2A, 0x03, 0xD0, + 0x07, 0x2A, 0x01, 0xD0, 0x08, 0x2A, 0x02, 0xD1, 0x40, 0x1C, 0xC0, 0xB2, 0x0C, 0x60, 0x5B, 0x1C, + 0xDB, 0xB2, 0x0F, 0x2B, 0xE0, 0xD3, 0x30, 0xBD, 0x09, 0x28, 0x0E, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, + 0x0D, 0x05, 0x05, 0x07, 0x09, 0x09, 0x09, 0x0B, 0x0B, 0x00, 0x04, 0x20, 0x70, 0x47, 0x01, 0x20, + 0x70, 0x47, 0x02, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x05, 0x20, 0x70, 0x47, 0x70, 0xB5, + 0x1A, 0x49, 0x0A, 0x78, 0x17, 0x49, 0x06, 0x2A, 0x05, 0xD0, 0x22, 0xB1, 0x05, 0x2A, 0x02, 0xD0, + 0x0A, 0x20, 0x08, 0x70, 0x70, 0xBD, 0x0A, 0x78, 0x22, 0xB1, 0x52, 0x1E, 0x12, 0xF0, 0xFF, 0x02, + 0x0A, 0x70, 0xF7, 0xD1, 0x05, 0x46, 0x00, 0x24, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, + 0x05, 0xEB, 0x00, 0x16, 0x31, 0x46, 0x28, 0x46, 0x03, 0xF0, 0xBC, 0xF8, 0x31, 0x46, 0x28, 0x46, + 0x03, 0xF0, 0xF1, 0xF8, 0x64, 0x1C, 0xE4, 0xB2, 0x0F, 0x2C, 0xED, 0xD3, 0xBD, 0xE8, 0x70, 0x40, + 0x10, 0x21, 0x01, 0x20, 0x0D, 0xF0, 0xB7, 0xBA, 0x7C, 0x6C, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x78, 0x06, 0x10, 0x00, 0x40, 0x05, 0x10, 0x00, 0xA0, 0x24, 0x10, 0x00, 0x30, 0x05, 0x10, 0x00, + 0x70, 0x47, 0xA5, 0x4A, 0x30, 0xB4, 0x12, 0x68, 0x92, 0xF8, 0xA4, 0x23, 0x12, 0x09, 0x80, 0xF8, + 0x28, 0x20, 0x0A, 0x68, 0x02, 0x62, 0x4A, 0x68, 0x42, 0x62, 0xB1, 0xF9, 0x02, 0x20, 0xD3, 0x17, + 0x1B, 0x04, 0x43, 0xEA, 0x12, 0x43, 0x12, 0x04, 0x82, 0x60, 0xC3, 0x60, 0xB1, 0xF9, 0x00, 0x10, + 0xCA, 0x17, 0x12, 0x04, 0x42, 0xEA, 0x11, 0x42, 0x09, 0x04, 0x01, 0x60, 0x42, 0x60, 0x10, 0x22, + 0x01, 0x46, 0x30, 0xBC, 0x10, 0x30, 0x0F, 0xF0, 0x15, 0xBB, 0x2D, 0xE9, 0xF0, 0x4F, 0x92, 0x4F, + 0x81, 0x46, 0x8A, 0x46, 0x38, 0x68, 0x8F, 0xB0, 0x16, 0x46, 0xB0, 0xF8, 0xA6, 0x13, 0x90, 0xF8, + 0xAA, 0x53, 0x01, 0xFB, 0x01, 0xFB, 0xB0, 0xF8, 0xA8, 0x13, 0x01, 0xFB, 0x01, 0xF8, 0x0F, 0xF0, + 0x53, 0xFC, 0x00, 0x28, 0x38, 0x68, 0x02, 0xD0, 0x90, 0xF8, 0xAC, 0x43, 0x01, 0xE0, 0x90, 0xF8, + 0xAB, 0x43, 0xAC, 0x42, 0x00, 0xD2, 0x25, 0x46, 0x00, 0x2E, 0x02, 0xDB, 0x89, 0xF8, 0x28, 0x60, + 0x19, 0xE0, 0x09, 0xF1, 0x24, 0x01, 0x99, 0xF8, 0x28, 0x60, 0x08, 0x1F, 0x0A, 0xF0, 0x11, 0xF9, + 0x58, 0x45, 0x01, 0xDB, 0x26, 0x46, 0x02, 0xE0, 0x40, 0x45, 0x00, 0xDC, 0x2E, 0x46, 0x38, 0x68, + 0x99, 0xF8, 0x28, 0x10, 0x90, 0xF8, 0xA4, 0x03, 0x00, 0xF0, 0x0F, 0x02, 0x30, 0x46, 0x0A, 0xF0, + 0x23, 0xF9, 0x89, 0xF8, 0x28, 0x00, 0x99, 0xF8, 0x28, 0x10, 0x74, 0x48, 0x00, 0xEB, 0x81, 0x00, + 0x01, 0x68, 0xCA, 0x17, 0xCD, 0xE9, 0x07, 0x21, 0x41, 0x6C, 0xCA, 0x17, 0xCD, 0xE9, 0x04, 0x12, + 0xD0, 0xF8, 0xCC, 0x20, 0xD0, 0xF8, 0x88, 0x50, 0xD4, 0x17, 0x01, 0x94, 0x93, 0x46, 0xDD, 0xE9, + 0x07, 0x21, 0xD9, 0xF8, 0x08, 0x30, 0xD9, 0xF8, 0x0C, 0x40, 0xA3, 0xFB, 0x01, 0x07, 0x04, 0xFB, + 0x01, 0x71, 0x03, 0xFB, 0x02, 0x11, 0xEE, 0x17, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, + 0x8D, 0xFA, 0xBA, 0xF9, 0x02, 0x30, 0xB9, 0xF9, 0x26, 0x20, 0x01, 0x9C, 0x9F, 0x18, 0xA7, 0xFB, + 0x0B, 0x38, 0x4F, 0xEA, 0xE7, 0x7C, 0x0C, 0xFB, 0x0B, 0x82, 0x07, 0xFB, 0x04, 0x24, 0xB9, 0xF9, + 0x22, 0x20, 0xA2, 0xFB, 0x05, 0xC8, 0xD7, 0x17, 0x07, 0xFB, 0x05, 0x87, 0x13, 0xEB, 0x0C, 0x03, + 0x02, 0xFB, 0x06, 0x72, 0x54, 0x41, 0x1F, 0x1A, 0x64, 0xEB, 0x01, 0x04, 0xDD, 0xE9, 0x04, 0x12, + 0xD9, 0xF8, 0x18, 0x30, 0xD9, 0xF8, 0x1C, 0xC0, 0xA3, 0xFB, 0x01, 0x08, 0x0C, 0xFB, 0x01, 0x81, + 0x03, 0xFB, 0x02, 0x11, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0x5F, 0xFA, 0x38, 0x1A, + 0x64, 0xEB, 0x01, 0x04, 0xCD, 0xE9, 0x0D, 0x04, 0x06, 0x94, 0x0A, 0x90, 0xDD, 0xE9, 0x07, 0x21, + 0xD9, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x04, 0x40, 0xA3, 0xFB, 0x01, 0x07, 0x04, 0xFB, 0x01, 0x71, + 0x03, 0xFB, 0x02, 0x11, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0x47, 0xFA, 0xBA, 0xF9, + 0x00, 0x30, 0xB9, 0xF9, 0x24, 0x20, 0x01, 0x9C, 0x13, 0x44, 0xA3, 0xFB, 0x0B, 0xC8, 0xDF, 0x17, + 0x07, 0xFB, 0x0B, 0x82, 0x03, 0xFB, 0x04, 0x27, 0xB9, 0xF9, 0x20, 0x20, 0xA2, 0xFB, 0x05, 0x48, + 0xD3, 0x17, 0x03, 0xFB, 0x05, 0x83, 0x02, 0xFB, 0x06, 0x32, 0x1C, 0xEB, 0x04, 0x03, 0x57, 0x41, + 0x1C, 0x1A, 0x67, 0xEB, 0x01, 0x07, 0xDD, 0xE9, 0x04, 0x12, 0xD9, 0xF8, 0x10, 0x30, 0xD9, 0xF8, + 0x14, 0x50, 0xA3, 0xFB, 0x01, 0x06, 0x05, 0xFB, 0x01, 0x61, 0x03, 0xFB, 0x02, 0x11, 0x4F, 0xF4, + 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0x1A, 0xFA, 0x25, 0x1A, 0x67, 0xEB, 0x01, 0x07, 0xCD, 0xE9, + 0x0B, 0x57, 0xD9, 0xF8, 0x20, 0x10, 0xC9, 0xF8, 0x24, 0x10, 0xDA, 0xF8, 0x00, 0x10, 0xC9, 0xF8, + 0x20, 0x10, 0x10, 0x22, 0x49, 0x46, 0x09, 0xF1, 0x10, 0x00, 0x0F, 0xF0, 0x2B, 0xFA, 0x10, 0x22, + 0x0B, 0xA9, 0x48, 0x46, 0x0F, 0xF0, 0x26, 0xFA, 0x0A, 0x98, 0x4F, 0xF4, 0x00, 0x41, 0x06, 0x9C, + 0x40, 0x18, 0x44, 0xF1, 0x00, 0x01, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0xF6, 0xF9, + 0xAA, 0xF8, 0x02, 0x00, 0x4F, 0xF4, 0x00, 0x40, 0x28, 0x18, 0x47, 0xF1, 0x00, 0x01, 0x4F, 0xF4, + 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0xEA, 0xF9, 0xAA, 0xF8, 0x00, 0x00, 0x0F, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0x70, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x01, 0x46, 0x10, 0x22, 0x10, 0x30, 0x0F, 0xF0, + 0x01, 0xFA, 0xB5, 0xF9, 0x02, 0x00, 0xC1, 0x17, 0x09, 0x04, 0x41, 0xEA, 0x10, 0x41, 0x00, 0x04, + 0xA0, 0x60, 0xE1, 0x60, 0xB5, 0xF9, 0x00, 0x00, 0xC1, 0x17, 0x09, 0x04, 0x41, 0xEA, 0x10, 0x41, + 0x00, 0x04, 0x20, 0x60, 0x61, 0x60, 0x70, 0xBD, 0x20, 0x07, 0x10, 0x00, 0x1A, 0x6B, 0x01, 0x00, + 0x30, 0xB5, 0x2A, 0x49, 0x0B, 0x68, 0x93, 0xF8, 0x14, 0x14, 0x89, 0x07, 0x17, 0xD5, 0x41, 0xF2, + 0xB0, 0x34, 0x0E, 0x21, 0x24, 0x58, 0x01, 0x22, 0x02, 0xFA, 0x01, 0xF5, 0x2C, 0x42, 0x0F, 0xD0, + 0xC1, 0xEB, 0xC1, 0x05, 0x05, 0xEB, 0x45, 0x05, 0x00, 0xEB, 0x05, 0x15, 0x95, 0xF8, 0x3F, 0x51, + 0x6D, 0x07, 0x05, 0xD5, 0x1E, 0x48, 0x93, 0xF8, 0x15, 0x14, 0x01, 0x70, 0x42, 0x70, 0x30, 0xBD, + 0x49, 0x1E, 0xE9, 0xD2, 0x30, 0xBD, 0x19, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x14, 0x14, 0x89, 0x07, + 0x09, 0xD5, 0x17, 0x49, 0x10, 0xB1, 0x00, 0x20, 0x48, 0x70, 0x03, 0xE0, 0x08, 0x78, 0x00, 0x28, + 0x01, 0xD0, 0x40, 0x1E, 0x08, 0x70, 0x70, 0x47, 0x10, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x14, 0x14, + 0x8A, 0x07, 0x06, 0xD5, 0x0E, 0x49, 0x4A, 0x78, 0x01, 0x2A, 0x08, 0xD0, 0x09, 0x78, 0x31, 0xB9, + 0x70, 0x47, 0xC9, 0x07, 0xFC, 0xD0, 0x90, 0xF8, 0x3F, 0x11, 0x04, 0x29, 0xF8, 0xD1, 0x90, 0xF8, + 0x3E, 0x11, 0x03, 0x29, 0x05, 0xD0, 0x04, 0x29, 0x01, 0xD0, 0x06, 0x29, 0xF0, 0xD1, 0x08, 0x21, + 0x00, 0xE0, 0x02, 0x21, 0x80, 0xF8, 0x3E, 0x11, 0x70, 0x47, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x58, 0x05, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x84, 0xF8, 0x42, 0x01, 0xE9, 0x48, + 0xE9, 0x4D, 0x0E, 0x46, 0x01, 0x78, 0x28, 0x68, 0x11, 0xB9, 0xE8, 0x49, 0x09, 0x78, 0x41, 0xB1, + 0x94, 0xF9, 0x4A, 0x11, 0x90, 0xF8, 0x63, 0x02, 0xB1, 0x42, 0x0D, 0xD1, 0x00, 0xF0, 0x0F, 0x00, + 0x0B, 0xE0, 0x0F, 0xF0, 0xC9, 0xFA, 0x00, 0x28, 0x94, 0xF9, 0x4A, 0x01, 0x0D, 0xD0, 0xB0, 0x42, + 0x28, 0x68, 0x90, 0xF8, 0x9B, 0x03, 0xF1, 0xD0, 0x00, 0x09, 0x84, 0xF8, 0x42, 0x01, 0x20, 0x46, + 0x00, 0xF0, 0x2A, 0xF9, 0x01, 0x28, 0x06, 0xD0, 0x0F, 0xE0, 0xB0, 0x42, 0x28, 0x68, 0x90, 0xF8, + 0x9A, 0x03, 0xE3, 0xD0, 0xF0, 0xE7, 0x29, 0x68, 0x94, 0xF8, 0x42, 0x01, 0x91, 0xF8, 0x9C, 0x13, + 0x01, 0xF0, 0x0F, 0x01, 0x08, 0x44, 0x84, 0xF8, 0x42, 0x01, 0xD1, 0x48, 0xD1, 0x49, 0x00, 0x78, + 0x09, 0x78, 0x08, 0x43, 0x07, 0xD0, 0x29, 0x68, 0x94, 0xF8, 0x42, 0x01, 0x91, 0xF8, 0x9D, 0x13, + 0x08, 0x44, 0x84, 0xF8, 0x42, 0x01, 0x70, 0xBD, 0xCB, 0x49, 0x00, 0x20, 0x08, 0x70, 0xCB, 0x49, + 0x08, 0x70, 0xCB, 0x49, 0x08, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, 0x00, 0xF5, 0x80, 0x55, + 0x04, 0x46, 0xB5, 0xF8, 0xB0, 0x03, 0x4F, 0xF0, 0x00, 0x0A, 0x00, 0x04, 0xC2, 0x4E, 0xD1, 0x46, + 0x00, 0x0C, 0x0D, 0xD0, 0x20, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0x30, 0x46, 0x4F, 0xF0, 0xFF, 0x37, + 0x00, 0x78, 0x39, 0x46, 0x4F, 0xF0, 0x00, 0x48, 0x4F, 0xF0, 0x01, 0x0B, 0x18, 0xBB, 0x08, 0xE0, + 0xBA, 0x49, 0x00, 0x20, 0x30, 0x70, 0x08, 0x70, 0xBD, 0xE8, 0xF8, 0x4F, 0x01, 0x20, 0xFF, 0xF7, + 0x52, 0xBF, 0x04, 0xF5, 0x80, 0x52, 0x00, 0x20, 0x92, 0xF9, 0xB8, 0x63, 0x22, 0xE0, 0x00, 0xBF, + 0xD2, 0xF8, 0xB0, 0xC3, 0x0B, 0xFA, 0x00, 0xF3, 0x1C, 0xEA, 0x03, 0x0F, 0x18, 0xD0, 0xC0, 0xEB, + 0xC0, 0x03, 0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x03, 0x13, 0x93, 0xF8, 0x3E, 0xC1, 0xBC, 0xF1, + 0x01, 0x0F, 0x01, 0xD0, 0x39, 0x46, 0x0F, 0xE0, 0xB3, 0xF8, 0x44, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, + 0x06, 0xD0, 0x5B, 0x6B, 0x93, 0xFB, 0xFC, 0xF3, 0x98, 0x45, 0x01, 0xDA, 0x98, 0x46, 0x01, 0x46, + 0x40, 0x1C, 0x40, 0xB2, 0x86, 0x42, 0xDB, 0xDA, 0x00, 0x27, 0xDF, 0xF8, 0x6C, 0x82, 0x00, 0x91, + 0x9A, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, 0x0B, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x72, 0xD0, + 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x04, 0xEB, 0x00, 0x16, 0x96, 0xF8, 0x3E, 0x01, + 0x01, 0x28, 0x02, 0xD0, 0x05, 0x28, 0x08, 0xD0, 0x10, 0xE0, 0x30, 0x46, 0x00, 0x99, 0xFF, 0xF7, + 0x41, 0xFF, 0x02, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x11, 0xE0, 0x30, 0x46, 0x00, 0xF0, 0xA8, 0xF8, + 0x06, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x30, 0x46, 0x00, 0xF0, 0xDB, 0xF8, 0x96, 0xF8, 0x3E, 0x01, + 0x02, 0x28, 0x04, 0xD0, 0x06, 0x28, 0x30, 0xD0, 0x07, 0x28, 0x39, 0xD0, 0x3E, 0xE0, 0x96, 0xF8, + 0x42, 0x00, 0xC0, 0x07, 0x12, 0xD0, 0x30, 0x46, 0x00, 0xF0, 0x76, 0xF8, 0x70, 0xB9, 0xD8, 0xF8, + 0x00, 0x00, 0x96, 0xF8, 0x42, 0x11, 0x90, 0xF8, 0x9C, 0x03, 0x00, 0xF0, 0x0F, 0x00, 0x81, 0x42, + 0x01, 0xD9, 0x08, 0x1A, 0x00, 0xE0, 0x00, 0x20, 0x86, 0xF8, 0x42, 0x01, 0x78, 0x48, 0x00, 0x78, + 0x40, 0xB1, 0x96, 0xF8, 0x42, 0x01, 0x08, 0xBB, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x9D, 0x03, + 0x86, 0xF8, 0x42, 0x01, 0x96, 0xF8, 0x42, 0x01, 0xC0, 0xB9, 0x03, 0x20, 0x86, 0xF8, 0x3E, 0x01, + 0x71, 0x48, 0x01, 0x78, 0x49, 0x1C, 0x01, 0x70, 0x10, 0xE0, 0x96, 0xF8, 0x43, 0x01, 0x68, 0xB9, + 0x96, 0xF8, 0x42, 0x00, 0x80, 0x07, 0x03, 0xD5, 0x07, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x05, 0xE0, + 0x08, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x30, 0x46, 0x00, 0xF0, 0x8C, 0xF8, 0x30, 0x46, 0xFF, 0xF7, + 0xC3, 0xFE, 0x96, 0xF8, 0x3E, 0x01, 0x02, 0x28, 0x06, 0xD0, 0x06, 0x28, 0x0B, 0xD0, 0x03, 0x28, + 0x10, 0xD0, 0x04, 0x28, 0x0E, 0xD0, 0x1D, 0xE0, 0x96, 0xF8, 0x42, 0x01, 0xD0, 0xB1, 0x40, 0x1E, + 0x86, 0xF8, 0x42, 0x01, 0x16, 0xE0, 0x96, 0xF8, 0x43, 0x01, 0x98, 0xB1, 0x40, 0x1E, 0x86, 0xF8, + 0x43, 0x01, 0x0F, 0xE0, 0x96, 0xF8, 0x3F, 0x01, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x28, 0x05, 0xD0, + 0x08, 0xE0, 0x09, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x09, 0x03, 0xE0, 0x0A, 0xF1, 0x01, 0x00, + 0x00, 0xF0, 0xFF, 0x0A, 0x7F, 0x1C, 0x7F, 0xB2, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xBF, 0xF6, + 0x61, 0xAF, 0x00, 0x20, 0xFF, 0xF7, 0x7F, 0xFE, 0x4E, 0x49, 0x81, 0xF8, 0x00, 0xA0, 0x4E, 0x49, + 0x81, 0xF8, 0x00, 0x90, 0xBD, 0xE8, 0xF8, 0x8F, 0x90, 0xF8, 0x5B, 0x10, 0x90, 0xF8, 0x5A, 0x20, + 0x8A, 0x1A, 0xB0, 0xF8, 0x42, 0x10, 0x52, 0x1C, 0x02, 0x2A, 0x0B, 0xD9, 0x90, 0xF8, 0x5D, 0x20, + 0x90, 0xF8, 0x5C, 0x30, 0x9A, 0x42, 0x05, 0xD1, 0x41, 0xF0, 0x01, 0x01, 0xA0, 0xF8, 0x42, 0x10, + 0x01, 0x20, 0x70, 0x47, 0x21, 0xF0, 0x01, 0x01, 0xA0, 0xF8, 0x42, 0x10, 0x00, 0x20, 0x70, 0x47, + 0x70, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x84, 0xF8, 0x43, 0x01, 0x32, 0x48, 0x32, 0x4D, 0x01, 0x78, + 0x28, 0x68, 0x51, 0xB1, 0x90, 0xF8, 0x64, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x84, 0xF8, 0x43, 0x01, + 0x94, 0xF8, 0x42, 0x00, 0x80, 0x07, 0x0E, 0xD5, 0x70, 0xBD, 0x2C, 0x49, 0x09, 0x78, 0x00, 0x29, + 0xF0, 0xD1, 0x0F, 0xF0, 0x59, 0xF9, 0x00, 0x28, 0x28, 0x68, 0x90, 0xF8, 0x9E, 0x03, 0xEB, 0xD0, + 0x00, 0x09, 0x84, 0xF8, 0x43, 0x01, 0x28, 0x68, 0xE1, 0x6A, 0x90, 0xF8, 0x9F, 0x03, 0x00, 0xF0, + 0x0F, 0x02, 0x91, 0x42, 0xE8, 0xD9, 0x94, 0xF8, 0x43, 0x11, 0x01, 0xEB, 0x10, 0x10, 0x84, 0xF8, + 0x43, 0x01, 0x70, 0xBD, 0x20, 0x49, 0x08, 0x78, 0x00, 0x28, 0x01, 0xD0, 0x40, 0x1E, 0x08, 0x70, + 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x18, 0x4D, 0x04, 0x46, 0x28, 0x68, 0x90, 0xF8, 0x81, 0x03, + 0xC0, 0x07, 0x24, 0xD0, 0x21, 0x46, 0x20, 0x1D, 0x09, 0xF0, 0x03, 0xFE, 0x07, 0x46, 0x21, 0x46, + 0x04, 0xF1, 0x20, 0x00, 0x09, 0xF0, 0xFD, 0xFD, 0x06, 0x46, 0x0F, 0xF0, 0x25, 0xF9, 0x00, 0x28, + 0x28, 0x68, 0x05, 0xD0, 0xB0, 0xF8, 0x93, 0x13, 0xB0, 0xF8, 0x8F, 0x03, 0x49, 0x43, 0x04, 0xE0, + 0xB0, 0xF8, 0x91, 0x13, 0xB0, 0xF8, 0x8D, 0x03, 0x49, 0x43, 0x40, 0x43, 0x86, 0x42, 0x06, 0xDD, + 0x8F, 0x42, 0x04, 0xDD, 0x34, 0xF8, 0x42, 0x0F, 0x40, 0xF0, 0x02, 0x00, 0x20, 0x80, 0xBD, 0xE8, + 0xF0, 0x81, 0x00, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, + 0x52, 0x06, 0x10, 0x00, 0x52, 0x07, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, 0xF3, 0x06, 0x10, 0x00, + 0xC5, 0x06, 0x10, 0x00, 0xC7, 0x06, 0x10, 0x00, 0xC8, 0x06, 0x10, 0x00, 0xF8, 0xB5, 0x07, 0x46, + 0xFD, 0x48, 0x0E, 0x46, 0xFE, 0x4C, 0x01, 0x78, 0xFC, 0x48, 0x15, 0x46, 0x00, 0x78, 0x01, 0xB9, + 0x88, 0xB1, 0x20, 0x68, 0x90, 0xF8, 0xBE, 0x13, 0xB0, 0xF8, 0xC9, 0x23, 0x01, 0xF0, 0x0F, 0x03, + 0x0C, 0x09, 0xB0, 0xF8, 0xC7, 0x13, 0x49, 0x43, 0x52, 0x43, 0x30, 0x46, 0x00, 0x94, 0x09, 0xF0, + 0xBE, 0xFD, 0x2C, 0x60, 0xF8, 0xBD, 0x0F, 0xF0, 0xD7, 0xF8, 0x58, 0xB1, 0x20, 0x68, 0x90, 0xF8, + 0xB4, 0x13, 0xB0, 0xF8, 0xB7, 0x23, 0x01, 0xF0, 0x0F, 0x03, 0x0C, 0x09, 0xB0, 0xF8, 0xB5, 0x13, + 0x49, 0x43, 0xE9, 0xE7, 0x97, 0xF8, 0x3F, 0x01, 0x02, 0x28, 0x0E, 0xD0, 0x01, 0x28, 0x20, 0x68, + 0x0F, 0xD0, 0x90, 0xF8, 0xB9, 0x13, 0x00, 0xBF, 0x01, 0xF0, 0x0F, 0x03, 0x0C, 0x09, 0xB0, 0xF8, + 0xBF, 0x13, 0xB0, 0xF8, 0xC1, 0x23, 0x49, 0x43, 0xD6, 0xE7, 0x20, 0x68, 0x90, 0xF8, 0xBA, 0x13, + 0xF2, 0xE7, 0x90, 0xF8, 0xBB, 0x13, 0xB0, 0xF8, 0xC5, 0x23, 0x01, 0xF0, 0x0F, 0x03, 0x0C, 0x09, + 0xB0, 0xF8, 0xC3, 0x13, 0x49, 0x43, 0xC7, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x90, 0xF8, + 0x3E, 0x01, 0x88, 0x46, 0x04, 0xF1, 0x78, 0x07, 0x03, 0x28, 0x0B, 0xD0, 0xD4, 0x4E, 0x04, 0x28, + 0x0D, 0xD0, 0x07, 0x28, 0x3B, 0xD0, 0x08, 0x28, 0x37, 0xD1, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x43, + 0x00, 0xF0, 0xCB, 0xBB, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0x00, 0xF0, 0x94, 0xBB, 0x20, 0x46, + 0x0F, 0xF0, 0x9F, 0xF8, 0x18, 0xB1, 0x20, 0x46, 0x0F, 0xF0, 0x96, 0xF8, 0x1D, 0xE0, 0x04, 0xF1, + 0x0C, 0x01, 0x08, 0x1D, 0x09, 0xF0, 0x55, 0xFD, 0x01, 0x46, 0x6A, 0x46, 0x20, 0x46, 0xFF, 0xF7, + 0x85, 0xFF, 0x05, 0x46, 0x94, 0xF8, 0x41, 0x01, 0x80, 0xB9, 0x20, 0x46, 0x0F, 0xF0, 0x86, 0xF8, + 0x10, 0xB1, 0x00, 0x98, 0x85, 0x42, 0x09, 0xDB, 0x30, 0x68, 0xD4, 0xF8, 0x80, 0x10, 0x90, 0xF8, + 0xBC, 0x03, 0x02, 0x09, 0x28, 0x46, 0x09, 0xF0, 0x5F, 0xFD, 0x05, 0x46, 0x2A, 0x46, 0x41, 0x46, + 0x38, 0x46, 0x00, 0xF0, 0x6A, 0xFB, 0xC4, 0xF8, 0x80, 0x50, 0xBD, 0xE8, 0xF8, 0x83, 0x30, 0x68, + 0x00, 0x24, 0x90, 0xF8, 0x81, 0x13, 0x89, 0x07, 0x0A, 0xD5, 0x90, 0xF8, 0xBD, 0x03, 0x00, 0xF0, + 0x0F, 0x04, 0x0F, 0xF0, 0x51, 0xF8, 0x18, 0xB1, 0x30, 0x68, 0x90, 0xF8, 0xBD, 0x03, 0x04, 0x09, + 0x22, 0x46, 0x41, 0x46, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0x00, 0xF0, 0x66, 0xBB, 0x2D, 0xE9, + 0xF0, 0x43, 0xDF, 0xF8, 0x9C, 0x92, 0x4F, 0xF0, 0x00, 0x0C, 0xB0, 0xF9, 0x02, 0x30, 0xD9, 0xF8, + 0x00, 0x40, 0x67, 0x46, 0x66, 0x46, 0x65, 0x46, 0x00, 0x2B, 0x02, 0xDA, 0x4F, 0xF0, 0x01, 0x0C, + 0x04, 0xE0, 0xB4, 0xF8, 0x32, 0x80, 0x98, 0x45, 0x00, 0xDA, 0x01, 0x27, 0xB0, 0xF9, 0x00, 0x30, + 0x00, 0x2B, 0x01, 0xDA, 0x01, 0x26, 0x04, 0xE0, 0xB4, 0xF8, 0x34, 0x80, 0x98, 0x45, 0x00, 0xDA, + 0x01, 0x25, 0x00, 0x23, 0xBC, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0x0E, 0xB1, 0x43, 0x80, 0x03, 0xE0, + 0x4F, 0xB1, 0x26, 0xB1, 0x61, 0x8E, 0x38, 0xE0, 0x03, 0x80, 0xBD, 0xE8, 0xF0, 0x83, 0x15, 0xB1, + 0x62, 0x8E, 0x42, 0x80, 0x04, 0xE0, 0xBC, 0xF1, 0x00, 0x0F, 0x30, 0xD0, 0x2D, 0xB1, 0x43, 0x80, + 0xD9, 0xF8, 0x00, 0x10, 0x89, 0x8E, 0x01, 0x80, 0xEF, 0xE7, 0xB2, 0xF8, 0x02, 0xC0, 0xBC, 0xF1, + 0x00, 0x0F, 0x24, 0xD0, 0x43, 0x80, 0xB1, 0xF9, 0x02, 0x40, 0x67, 0x42, 0x2C, 0xE0, 0x00, 0xBF, + 0x0C, 0xFB, 0x07, 0xFC, 0x00, 0x2C, 0x00, 0xDA, 0x64, 0x42, 0x9C, 0xFB, 0xF4, 0xF4, 0x0F, 0x88, + 0x3C, 0x44, 0x04, 0x80, 0x46, 0xB3, 0xB2, 0xF9, 0x00, 0x40, 0x2C, 0xB3, 0xB1, 0xF9, 0x00, 0x50, + 0xB2, 0xF9, 0x02, 0x20, 0x6D, 0x42, 0x00, 0xD5, 0x6D, 0x42, 0x6A, 0x43, 0x00, 0x2C, 0x00, 0xDA, + 0x64, 0x42, 0x92, 0xFB, 0xF4, 0xF2, 0x49, 0x88, 0x11, 0x44, 0x41, 0x80, 0xC4, 0xE7, 0x00, 0x2F, + 0xE8, 0xD0, 0x57, 0x88, 0x00, 0x2F, 0xE5, 0xD0, 0x64, 0x8E, 0x44, 0x80, 0xD9, 0xF8, 0x00, 0x40, + 0xB1, 0xF9, 0x02, 0x70, 0x64, 0x8E, 0xE7, 0x1B, 0xB2, 0xF9, 0x02, 0x40, 0xB2, 0xF9, 0x00, 0xC0, + 0x00, 0x2F, 0xCD, 0xDA, 0x7F, 0x42, 0xCB, 0xE7, 0x00, 0x2D, 0xAE, 0xD0, 0xB2, 0xF9, 0x00, 0x30, + 0x00, 0x2B, 0xAA, 0xD0, 0xD9, 0xF8, 0x00, 0x40, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x02, 0x20, + 0xA4, 0x8E, 0xA4, 0x1B, 0x00, 0xD5, 0x64, 0x42, 0x62, 0x43, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, + 0x92, 0xFB, 0xF3, 0xF2, 0x49, 0x88, 0x11, 0x44, 0x41, 0x80, 0xA1, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, + 0x0D, 0x46, 0x5C, 0x49, 0x04, 0x46, 0x00, 0x20, 0x48, 0x80, 0x08, 0x80, 0xA1, 0xF1, 0x10, 0x08, + 0x28, 0x68, 0xC8, 0xF8, 0x00, 0x00, 0x17, 0x46, 0x4F, 0xF0, 0x01, 0x0A, 0x46, 0x46, 0x29, 0x46, + 0x20, 0x46, 0x00, 0xF0, 0x6D, 0xFF, 0xDF, 0xF8, 0x48, 0x91, 0x28, 0x68, 0x70, 0x60, 0xD9, 0xF8, + 0x00, 0x00, 0x04, 0xF1, 0x0C, 0x0B, 0x90, 0xF8, 0x80, 0x03, 0x41, 0x07, 0x22, 0xD5, 0x94, 0xF8, + 0x3E, 0x01, 0x04, 0xF1, 0x84, 0x06, 0x02, 0x28, 0x0A, 0xD0, 0x03, 0x28, 0x08, 0xD0, 0x04, 0x28, + 0x0B, 0xD0, 0x06, 0x28, 0x12, 0xD0, 0x07, 0x28, 0x10, 0xD0, 0x08, 0x28, 0x0E, 0xD0, 0x11, 0xE0, + 0x59, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0xED, 0xFA, 0x0C, 0xE0, 0x20, 0x46, 0x00, 0xF0, 0xD9, 0xF9, + 0x02, 0x46, 0x29, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x08, 0xFB, 0x03, 0xE0, 0x29, 0x46, 0x30, 0x46, + 0xFF, 0xF7, 0x0F, 0xFC, 0x29, 0x68, 0xC8, 0xF8, 0x08, 0x10, 0xD9, 0xF8, 0x00, 0x00, 0x4E, 0x46, + 0x90, 0xF8, 0x80, 0x03, 0x00, 0x07, 0x14, 0xD5, 0x94, 0xF8, 0x42, 0x00, 0x10, 0xF0, 0xC8, 0x0F, + 0x05, 0xD0, 0x32, 0x48, 0x00, 0x78, 0x10, 0xB9, 0x2F, 0x48, 0x00, 0x78, 0x20, 0xB1, 0x29, 0x46, + 0x20, 0x46, 0x00, 0xF0, 0xE6, 0xF9, 0x04, 0xE0, 0x59, 0x46, 0x04, 0xF1, 0xB0, 0x00, 0x00, 0xF0, + 0xEE, 0xFD, 0x29, 0x68, 0xC8, 0xF8, 0x0C, 0x10, 0x30, 0x68, 0x90, 0xF8, 0x80, 0x13, 0x49, 0x06, + 0x0F, 0xD4, 0x90, 0xF8, 0x40, 0x14, 0x49, 0x06, 0x03, 0xD5, 0x94, 0xF8, 0x42, 0x10, 0x09, 0x07, + 0x07, 0xD4, 0x90, 0xF8, 0x20, 0x04, 0x80, 0x07, 0x08, 0xD5, 0x94, 0xF8, 0x42, 0x00, 0x00, 0x06, + 0x04, 0xD5, 0x29, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x37, 0xFE, 0x82, 0x46, 0x30, 0x68, 0x90, 0xF8, + 0x80, 0x03, 0x80, 0x06, 0x03, 0xD5, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x7D, 0xFE, 0x30, 0x68, + 0x90, 0xF8, 0x80, 0x03, 0x01, 0x07, 0x0B, 0xD5, 0xC0, 0x06, 0x09, 0xD5, 0x94, 0xF8, 0x3E, 0x01, + 0x07, 0x28, 0x05, 0xD1, 0x13, 0x4A, 0x04, 0xF1, 0xF4, 0x01, 0x28, 0x46, 0xFF, 0xF7, 0xCF, 0xFE, + 0x30, 0x68, 0xB0, 0xF9, 0x32, 0x10, 0xB5, 0xF9, 0x02, 0x00, 0x09, 0xF0, 0xAB, 0xFB, 0x68, 0x80, + 0x30, 0x68, 0xB0, 0xF9, 0x34, 0x10, 0xB5, 0xF9, 0x00, 0x00, 0x09, 0xF0, 0xA3, 0xFB, 0x28, 0x80, + 0x94, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x0F, 0xD0, 0x04, 0x28, 0x11, 0xD0, 0x07, 0x28, 0x1F, 0xD0, + 0x08, 0x28, 0x1D, 0xD0, 0x1F, 0xE0, 0x00, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x6A, 0x05, 0x10, 0x00, 0x38, 0x88, 0xA4, 0xF8, 0x50, 0x00, 0x12, 0xE0, + 0x30, 0x68, 0x34, 0xF8, 0x50, 0x2F, 0x90, 0xF8, 0xBC, 0x03, 0x00, 0xF0, 0x0F, 0x01, 0xC1, 0xF1, + 0x10, 0x00, 0x4A, 0x43, 0x39, 0x88, 0x01, 0xFB, 0x00, 0x20, 0x00, 0x09, 0x20, 0x80, 0x01, 0xE0, + 0xB4, 0xF8, 0x50, 0x00, 0x38, 0x80, 0x50, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xF3, 0x4F, + 0xE1, 0x49, 0x83, 0xB0, 0x4F, 0xF0, 0x00, 0x08, 0xC1, 0xF8, 0x00, 0x80, 0xDF, 0x49, 0xE0, 0x4D, + 0x83, 0x46, 0xC1, 0xF8, 0x00, 0x80, 0x85, 0xF8, 0x00, 0x80, 0x46, 0x46, 0xDF, 0xF8, 0x74, 0xA3, + 0x4F, 0xF0, 0x01, 0x09, 0x00, 0xF5, 0x80, 0x57, 0x6A, 0xE0, 0x00, 0xBF, 0xD7, 0xF8, 0xB0, 0x13, + 0x09, 0xFA, 0x06, 0xF0, 0x01, 0x42, 0x62, 0xD0, 0xC6, 0xEB, 0xC6, 0x00, 0x00, 0xEB, 0x40, 0x00, + 0x0B, 0xEB, 0x00, 0x14, 0x94, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x05, 0xD0, 0x04, 0x28, 0x03, 0xD0, + 0x07, 0x28, 0x01, 0xD0, 0x08, 0x28, 0x52, 0xD1, 0xE0, 0x68, 0x00, 0x90, 0xB4, 0xF8, 0x4E, 0x00, + 0xAD, 0xF8, 0x04, 0x00, 0x04, 0xF1, 0x0C, 0x01, 0xC7, 0x4A, 0x08, 0x1D, 0x00, 0xF0, 0xF8, 0xF8, + 0x01, 0xAA, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xE9, 0xFE, 0x02, 0x90, 0xC3, 0x4A, 0x69, 0x46, + 0x04, 0xF1, 0x24, 0x00, 0x00, 0xF0, 0xEC, 0xF8, 0xDA, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x00, 0x04, + 0xC0, 0x07, 0x0E, 0xD0, 0x94, 0xF8, 0x42, 0x00, 0x40, 0x07, 0x02, 0xD5, 0x00, 0x20, 0x02, 0x90, + 0x07, 0xE0, 0x94, 0xF8, 0x34, 0x01, 0x01, 0x28, 0x03, 0xD1, 0x20, 0x6A, 0x00, 0x90, 0x84, 0xF8, + 0x34, 0x81, 0x94, 0xF8, 0x3F, 0x01, 0x03, 0x28, 0x09, 0xD1, 0x28, 0x78, 0x40, 0x1C, 0xC0, 0xB2, + 0x28, 0x70, 0x94, 0xF8, 0x42, 0x10, 0x49, 0x07, 0x01, 0xD5, 0x40, 0x1E, 0x28, 0x70, 0x00, 0x98, + 0x60, 0x62, 0xBD, 0xF8, 0x04, 0x00, 0xA4, 0xF8, 0x50, 0x00, 0x02, 0x98, 0x01, 0x28, 0x0E, 0xD1, + 0x00, 0x98, 0xA0, 0x61, 0xBD, 0xF8, 0x04, 0x00, 0xA4, 0xF8, 0x52, 0x00, 0x04, 0x98, 0x94, 0xF8, + 0x4A, 0x21, 0x01, 0x68, 0x09, 0xFA, 0x02, 0xF0, 0x01, 0x43, 0x04, 0x98, 0x01, 0x60, 0x76, 0x1C, + 0x97, 0xF9, 0xB8, 0x03, 0xB0, 0x42, 0x91, 0xDA, 0xDA, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x00, 0x04, + 0x00, 0x07, 0x0E, 0xD5, 0x29, 0x78, 0xA0, 0x48, 0x29, 0xB1, 0xA0, 0x49, 0x09, 0x78, 0x01, 0x29, + 0x01, 0xD1, 0x80, 0xF8, 0x00, 0x90, 0xD7, 0xF8, 0xB4, 0x13, 0x00, 0x29, 0x01, 0xD1, 0x80, 0xF8, + 0x00, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xF0, 0x47, 0x89, 0x46, 0x06, 0x46, + 0x00, 0x27, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0xF5, 0x80, 0x55, 0x3C, 0xE0, 0xD5, 0xF8, 0xB0, 0x13, + 0x08, 0xFA, 0x07, 0xF2, 0x11, 0x42, 0x35, 0xD0, 0xC7, 0xEB, 0xC7, 0x01, 0x01, 0xEB, 0x41, 0x01, + 0x06, 0xEB, 0x01, 0x14, 0x94, 0xF8, 0x3E, 0x11, 0x03, 0x29, 0x05, 0xD0, 0x04, 0x29, 0x03, 0xD0, + 0x07, 0x29, 0x01, 0xD0, 0x08, 0x29, 0x25, 0xD1, 0x94, 0xF8, 0x4A, 0x31, 0xD9, 0xF8, 0x00, 0x20, + 0x08, 0xFA, 0x03, 0xF0, 0x02, 0x42, 0x1D, 0xD0, 0x03, 0x29, 0x03, 0xD1, 0x21, 0x46, 0x30, 0x46, + 0x02, 0xF0, 0x3E, 0xFA, 0x94, 0xF9, 0x4B, 0x01, 0x00, 0x28, 0x13, 0xDB, 0x94, 0xF8, 0x3F, 0x01, + 0x00, 0x21, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x04, 0xD0, 0x04, 0xE0, + 0x03, 0x21, 0x02, 0xE0, 0x04, 0x21, 0x00, 0xE0, 0x05, 0x21, 0x84, 0xF8, 0x40, 0x11, 0x20, 0x46, + 0x08, 0xF0, 0x04, 0xFD, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xBE, 0xDA, 0x00, 0x24, + 0x47, 0x46, 0x24, 0xE0, 0xD5, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x04, 0xF1, 0x08, 0x42, 0x1D, 0xD0, + 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x18, 0x98, 0xF8, 0x3E, 0x01, + 0x08, 0x28, 0x13, 0xD1, 0x98, 0xF8, 0x4A, 0x21, 0xD9, 0xF8, 0x00, 0x10, 0x07, 0xFA, 0x02, 0xF0, + 0x01, 0x42, 0x07, 0xD0, 0x98, 0xF9, 0x4B, 0x01, 0x00, 0x28, 0x03, 0xDB, 0x41, 0x46, 0x30, 0x46, + 0x02, 0xF0, 0x19, 0xFA, 0x41, 0x46, 0x30, 0x46, 0x02, 0xF0, 0xDC, 0xF9, 0x64, 0x1C, 0x95, 0xF9, + 0xB8, 0x03, 0xA0, 0x42, 0xD6, 0xDA, 0xBD, 0xE8, 0xF0, 0x87, 0x57, 0x49, 0x10, 0xB5, 0x00, 0x20, + 0x08, 0x60, 0x56, 0x49, 0x08, 0x60, 0xFF, 0xF7, 0x2B, 0xF9, 0x00, 0xF0, 0x39, 0xFC, 0xBD, 0xE8, + 0x10, 0x40, 0x00, 0xF0, 0xB7, 0xB8, 0x38, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x00, 0x90, 0x69, 0x46, + 0x20, 0x46, 0xFF, 0xF7, 0xD3, 0xFE, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x6D, 0xFF, 0x38, 0xBD, + 0x10, 0xB5, 0x14, 0x46, 0x09, 0xF0, 0x75, 0xFA, 0x21, 0x68, 0x81, 0x42, 0x00, 0xDA, 0x20, 0x60, + 0x10, 0xBD, 0x4B, 0x49, 0x10, 0xB5, 0x0B, 0x78, 0x46, 0x49, 0x02, 0x46, 0x4F, 0xF0, 0xFF, 0x30, + 0x09, 0x68, 0x13, 0xB1, 0x91, 0xF9, 0xAA, 0x03, 0x10, 0xBD, 0x46, 0x4B, 0x1B, 0x78, 0x00, 0x2B, + 0xF8, 0xD1, 0xB2, 0xF8, 0x42, 0x30, 0x5C, 0x06, 0x03, 0xD5, 0x91, 0xF8, 0xA5, 0x03, 0x00, 0x09, + 0x10, 0xBD, 0x1C, 0x07, 0x02, 0xD5, 0x91, 0xF8, 0x51, 0x04, 0x03, 0xE0, 0x1B, 0x06, 0x04, 0xD5, + 0x91, 0xF8, 0x2A, 0x04, 0x00, 0xF0, 0x0F, 0x00, 0x10, 0xBD, 0x92, 0xF8, 0x3F, 0x21, 0x01, 0x2A, + 0x04, 0xD0, 0x39, 0x4A, 0x12, 0x78, 0x01, 0x2A, 0xDC, 0xD8, 0x10, 0xBD, 0x91, 0xF8, 0xA5, 0x03, + 0xF0, 0xE7, 0x30, 0xB4, 0x0C, 0x46, 0x90, 0xF8, 0x3E, 0x11, 0x00, 0xF1, 0xB0, 0x03, 0x03, 0x29, + 0x23, 0xD0, 0x04, 0x29, 0x03, 0xD0, 0x06, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x41, 0xD1, 0x29, 0x4A, + 0x12, 0x68, 0x92, 0xF8, 0x80, 0x23, 0xD2, 0x06, 0x2D, 0xD5, 0x90, 0xF8, 0x5B, 0x20, 0x90, 0xF8, + 0x5A, 0x50, 0x52, 0x1B, 0xC0, 0xF8, 0x24, 0x21, 0x90, 0xF8, 0x5D, 0x20, 0x90, 0xF8, 0x5C, 0x50, + 0x52, 0x1B, 0xC0, 0xF8, 0x28, 0x21, 0x82, 0x6B, 0xC0, 0xF8, 0x20, 0x21, 0x23, 0x4A, 0x07, 0x29, + 0x12, 0x88, 0xC0, 0xF8, 0x2C, 0x21, 0x06, 0xD0, 0x0F, 0xE0, 0x00, 0xF1, 0x0C, 0x01, 0x30, 0xBC, + 0x18, 0x46, 0x00, 0xF0, 0xDC, 0xBB, 0x90, 0xF8, 0x31, 0x11, 0x03, 0x29, 0x05, 0xD9, 0x21, 0x46, + 0x30, 0xBC, 0x1B, 0x4A, 0x18, 0x46, 0x00, 0xF0, 0x6A, 0xBC, 0x90, 0xF8, 0x31, 0x11, 0x49, 0x1C, + 0x80, 0xF8, 0x31, 0x11, 0x03, 0xE0, 0x90, 0xF8, 0x31, 0x21, 0x03, 0x2A, 0x04, 0xD9, 0x21, 0x46, + 0x30, 0xBC, 0x18, 0x46, 0x00, 0xF0, 0x28, 0xBC, 0x04, 0x29, 0x04, 0xD0, 0x00, 0x21, 0x80, 0xF8, + 0x31, 0x11, 0x30, 0xBC, 0x70, 0x47, 0x52, 0x1C, 0x80, 0xF8, 0x31, 0x21, 0x21, 0x46, 0x30, 0xBC, + 0x18, 0x46, 0x00, 0xF0, 0x02, 0xBC, 0x00, 0x00, 0xF4, 0x06, 0x10, 0x00, 0xF8, 0x06, 0x10, 0x00, + 0xF3, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, + 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, 0x54, 0x06, 0x10, 0x00, + 0x6A, 0x05, 0x10, 0x00, 0x70, 0x47, 0x00, 0xF0, 0x35, 0xB8, 0x7C, 0xB5, 0x04, 0x46, 0x15, 0x46, + 0x0E, 0x46, 0x68, 0x46, 0x00, 0xF0, 0x2E, 0xF8, 0x01, 0x99, 0x2A, 0x46, 0x60, 0x68, 0x00, 0xF0, + 0x3B, 0xF8, 0x60, 0x60, 0x00, 0x99, 0x2A, 0x46, 0x20, 0x68, 0x00, 0xF0, 0x35, 0xF8, 0x20, 0x60, + 0x21, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x27, 0xF8, 0x7C, 0xBD, 0x7C, 0xB5, 0x04, 0x46, 0x15, 0x46, + 0x0E, 0x46, 0x68, 0x46, 0x00, 0xF0, 0x16, 0xF8, 0x01, 0x99, 0x2A, 0x46, 0x60, 0x68, 0x00, 0xF0, + 0x23, 0xF8, 0x60, 0x60, 0x00, 0x99, 0x2A, 0x46, 0x20, 0x68, 0x00, 0xF0, 0x1D, 0xF8, 0x20, 0x60, + 0x21, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x0F, 0xF8, 0x7C, 0xBD, 0x0A, 0x46, 0x01, 0x46, 0x10, 0x46, + 0x00, 0xF0, 0x09, 0xB8, 0xB1, 0xF9, 0x02, 0x20, 0x12, 0x02, 0x42, 0x60, 0xB1, 0xF9, 0x00, 0x10, + 0x09, 0x02, 0x01, 0x60, 0x70, 0x47, 0x4A, 0x68, 0x80, 0x32, 0x12, 0x12, 0x42, 0x80, 0x09, 0x68, + 0x80, 0x31, 0x09, 0x12, 0x01, 0x80, 0x70, 0x47, 0xC2, 0xF1, 0x10, 0x03, 0x50, 0x43, 0x01, 0xFB, + 0x03, 0x00, 0x00, 0x11, 0x70, 0x47, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xFE, 0x4A, 0x12, 0x68, + 0x51, 0xB3, 0x51, 0x8E, 0x92, 0xF8, 0x30, 0x30, 0x82, 0x6F, 0x04, 0x6F, 0xC0, 0x6F, 0x64, 0x26, + 0x40, 0x00, 0x00, 0xFB, 0x02, 0x40, 0x48, 0x43, 0xA0, 0xFB, 0x00, 0x25, 0x00, 0x21, 0x01, 0xFB, + 0x00, 0x55, 0x00, 0xFB, 0x01, 0x51, 0xA2, 0xFB, 0x06, 0x07, 0x00, 0x25, 0x01, 0xFB, 0x06, 0x71, + 0x02, 0xFB, 0x05, 0x11, 0x5C, 0x43, 0x22, 0x46, 0x2B, 0x46, 0x0E, 0xF0, 0x85, 0xFA, 0x22, 0x46, + 0x00, 0x23, 0x0E, 0xF0, 0x81, 0xFA, 0xED, 0x4B, 0x00, 0x22, 0x1B, 0x1A, 0x8A, 0x41, 0x01, 0xD2, + 0xEA, 0x48, 0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x81, 0x91, 0x8E, 0x92, 0xF8, 0x31, 0x30, 0x42, 0x6F, + 0xD3, 0xE7, 0x7C, 0xB5, 0x04, 0x46, 0xE6, 0x48, 0xB4, 0xF9, 0x02, 0x10, 0x00, 0x78, 0x01, 0x28, + 0x30, 0xD0, 0xB4, 0xF9, 0x06, 0x00, 0xB4, 0xF9, 0x0A, 0x20, 0x09, 0x1A, 0x80, 0x1A, 0x08, 0x1A, + 0x01, 0x90, 0xB4, 0xF9, 0x00, 0x10, 0xB4, 0xF9, 0x04, 0x00, 0xB4, 0xF9, 0x08, 0x20, 0x09, 0x1A, + 0x80, 0x1A, 0x08, 0x1A, 0xD8, 0x49, 0x00, 0x90, 0x20, 0x6C, 0x09, 0x68, 0x01, 0x9B, 0x91, 0xF8, + 0xB3, 0x23, 0x50, 0x43, 0xC2, 0xF1, 0x80, 0x02, 0x53, 0x43, 0xC2, 0x17, 0x00, 0xEB, 0x52, 0x60, + 0x03, 0xEB, 0xE0, 0x10, 0x20, 0x64, 0x91, 0xF8, 0xB3, 0x13, 0xE0, 0x6B, 0x00, 0x9A, 0x48, 0x43, + 0xC1, 0xF1, 0x80, 0x01, 0x4A, 0x43, 0xC1, 0x17, 0x00, 0xEB, 0x51, 0x60, 0x02, 0xEB, 0xE0, 0x10, + 0xE0, 0x63, 0x7C, 0xBD, 0xB4, 0xF9, 0x46, 0x00, 0xB4, 0xF9, 0x4A, 0x20, 0x09, 0x1A, 0x80, 0x1A, + 0x08, 0x1A, 0x01, 0x90, 0xB4, 0xF9, 0x00, 0x10, 0xB4, 0xF9, 0x44, 0x00, 0xB4, 0xF9, 0x48, 0x20, + 0x09, 0x1A, 0x80, 0x1A, 0x08, 0x1A, 0x00, 0x90, 0x04, 0xF1, 0x50, 0x00, 0x03, 0x22, 0x69, 0x46, + 0x05, 0x46, 0x09, 0xF0, 0xDC, 0xF8, 0x94, 0xF8, 0x80, 0x00, 0x03, 0x28, 0x02, 0xD2, 0x40, 0x1C, + 0x84, 0xF8, 0x80, 0x00, 0xC2, 0xB2, 0x29, 0x46, 0x04, 0xF1, 0x68, 0x00, 0x00, 0xF0, 0x98, 0xFB, + 0x7C, 0xBD, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x00, 0x26, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, + 0x01, 0x24, 0x0D, 0xF1, 0x14, 0x08, 0x08, 0x96, 0x02, 0x25, 0xCD, 0xE9, 0x01, 0x48, 0x07, 0x46, + 0xCD, 0xE9, 0x03, 0x54, 0x00, 0xF1, 0x0C, 0x03, 0xAD, 0x48, 0x9B, 0x46, 0x2A, 0x46, 0x29, 0x46, + 0x20, 0x30, 0x00, 0x95, 0x09, 0xF0, 0x2C, 0xF8, 0xDF, 0xF8, 0xA4, 0x92, 0x4F, 0xF4, 0x80, 0x7A, + 0x99, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x48, 0xD0, 0x38, 0x6C, 0x00, 0x90, 0x01, 0x23, 0x02, 0x22, + 0x07, 0xA9, 0x09, 0xF1, 0x08, 0x00, 0x08, 0xF0, 0xF2, 0xFF, 0x07, 0xA9, 0x01, 0x23, 0x02, 0x22, + 0x08, 0x46, 0xCD, 0xF8, 0x00, 0xA0, 0x08, 0xF0, 0xDC, 0xFF, 0x02, 0x23, 0x5A, 0x46, 0x07, 0xA9, + 0x05, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0xF0, 0xFF, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, 0x08, 0x96, + 0xCD, 0xE9, 0x01, 0x48, 0xCD, 0xE9, 0x03, 0x54, 0x95, 0x48, 0x07, 0xF1, 0x14, 0x03, 0x00, 0x95, + 0x02, 0x22, 0x1D, 0x46, 0x11, 0x46, 0x20, 0x30, 0x08, 0xF0, 0xFA, 0xFF, 0x99, 0xF8, 0x00, 0x00, + 0x01, 0x28, 0x1F, 0xD0, 0xF8, 0x6B, 0x00, 0x90, 0x8D, 0x48, 0x01, 0x23, 0x02, 0x22, 0x07, 0xA9, + 0x08, 0x30, 0x08, 0xF0, 0xC4, 0xFF, 0x07, 0xA9, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0xCD, 0xF8, + 0x00, 0xA0, 0x08, 0xF0, 0xAE, 0xFF, 0x02, 0x23, 0x2A, 0x46, 0x07, 0xA9, 0x05, 0xA8, 0x00, 0x94, + 0x08, 0xF0, 0xC2, 0xFF, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDD, 0xE9, 0x05, 0x01, 0xC7, 0xE9, + 0x03, 0x01, 0xC9, 0xE7, 0xDD, 0xE9, 0x05, 0x01, 0xC7, 0xE9, 0x05, 0x01, 0xF2, 0xE7, 0x2D, 0xE9, + 0xF0, 0x4F, 0x8D, 0xB0, 0x00, 0x26, 0x02, 0x24, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, 0x08, 0x96, + 0x09, 0x96, 0x0A, 0x96, 0x0B, 0x96, 0x05, 0xAF, 0x0C, 0x96, 0xCD, 0xE9, 0x01, 0x47, 0x05, 0x46, + 0x73, 0x48, 0x05, 0xF1, 0x1C, 0x03, 0x03, 0x94, 0x04, 0x94, 0x9B, 0x46, 0x22, 0x46, 0x21, 0x46, + 0x20, 0x30, 0x00, 0x94, 0x08, 0xF0, 0xB4, 0xFF, 0x0D, 0xF1, 0x24, 0x0A, 0xCD, 0xE9, 0x01, 0x4A, + 0x6B, 0x4B, 0x02, 0x22, 0x03, 0x94, 0x04, 0x94, 0x30, 0x33, 0x11, 0x46, 0x05, 0xA8, 0x00, 0x94, + 0x08, 0xF0, 0xA6, 0xFF, 0xDF, 0xF8, 0x98, 0x81, 0x4F, 0xF0, 0x04, 0x09, 0x98, 0xF8, 0x00, 0x00, + 0x01, 0x28, 0x12, 0xD1, 0xE8, 0x6E, 0x02, 0x23, 0x08, 0xF1, 0x60, 0x01, 0x00, 0x90, 0x1A, 0x46, + 0xA1, 0xF1, 0x10, 0x00, 0x08, 0xF0, 0x6B, 0xFF, 0x02, 0x23, 0x08, 0xF1, 0x60, 0x01, 0x1A, 0x46, + 0x08, 0x46, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0x54, 0xFF, 0x59, 0x49, 0x02, 0x23, 0x5A, 0x46, + 0x60, 0x31, 0x09, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0x67, 0xFF, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, + 0x08, 0x96, 0x09, 0x96, 0x0A, 0x96, 0x0B, 0x96, 0x0C, 0x96, 0xCD, 0xE9, 0x01, 0x47, 0x50, 0x48, + 0x05, 0xF1, 0x2C, 0x03, 0x02, 0x22, 0x03, 0x94, 0x04, 0x94, 0x1E, 0x46, 0x11, 0x46, 0x20, 0x30, + 0x00, 0x94, 0x08, 0xF0, 0x6D, 0xFF, 0xCD, 0xE9, 0x01, 0x4A, 0x49, 0x4B, 0x02, 0x22, 0x03, 0x94, + 0x04, 0x94, 0x30, 0x33, 0x11, 0x46, 0x05, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0x61, 0xFF, 0x98, 0xF8, + 0x00, 0x00, 0x01, 0x28, 0x12, 0xD1, 0x42, 0x49, 0xA8, 0x6E, 0x02, 0x23, 0x60, 0x31, 0x00, 0x90, + 0x1A, 0x46, 0xA1, 0xF1, 0x10, 0x00, 0x08, 0xF0, 0x2A, 0xFF, 0x3D, 0x49, 0x02, 0x23, 0x60, 0x31, + 0x1A, 0x46, 0x08, 0x46, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0x13, 0xFF, 0x38, 0x49, 0x02, 0x23, + 0x32, 0x46, 0x60, 0x31, 0x09, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0x26, 0xFF, 0x0D, 0xB0, 0x62, 0xE7, + 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x00, 0x26, 0x01, 0x24, 0x05, 0x96, 0x06, 0x96, 0x0D, 0xF1, + 0x14, 0x0A, 0x07, 0x96, 0xCD, 0xE9, 0x01, 0x4A, 0x05, 0x46, 0x00, 0xF1, 0x0C, 0x03, 0x4F, 0xF0, + 0x02, 0x09, 0x2B, 0x48, 0x93, 0x46, 0x0F, 0x46, 0x03, 0x94, 0x98, 0x46, 0x4A, 0x46, 0x21, 0x46, + 0x10, 0x30, 0xCD, 0xF8, 0x00, 0x90, 0x04, 0x94, 0x08, 0xF0, 0x22, 0xFF, 0xB5, 0xF9, 0x02, 0x00, + 0x05, 0x99, 0x01, 0x23, 0x40, 0x1A, 0x05, 0x90, 0x00, 0x90, 0x02, 0x22, 0x06, 0xA9, 0x38, 0x46, + 0x08, 0xF0, 0xED, 0xFE, 0x64, 0x27, 0x41, 0x46, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0x00, 0x97, + 0x08, 0xF0, 0xE5, 0xFE, 0x42, 0x46, 0x02, 0x23, 0x06, 0xA9, 0x10, 0x46, 0x00, 0x94, 0x08, 0xF0, + 0xEB, 0xFE, 0x41, 0x46, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0x00, 0x97, 0x08, 0xF0, 0xC9, 0xFE, + 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, 0xCD, 0xE9, 0x01, 0x4A, 0x11, 0x48, 0x05, 0xF1, 0x14, 0x03, + 0x03, 0x94, 0x1E, 0x46, 0x02, 0x22, 0x01, 0x21, 0x10, 0x30, 0xCD, 0xF8, 0x00, 0x90, 0x04, 0x94, + 0x08, 0xF0, 0xEE, 0xFE, 0xB5, 0xF9, 0x00, 0x00, 0x05, 0x99, 0x01, 0x23, 0x40, 0x1A, 0x05, 0x90, + 0x00, 0x90, 0x02, 0x22, 0x06, 0xA9, 0x58, 0x46, 0x08, 0xF0, 0xB9, 0xFE, 0x01, 0x23, 0x31, 0x46, + 0x02, 0x22, 0x08, 0x46, 0x00, 0x97, 0x05, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x40, 0x42, 0x0F, 0x00, + 0x70, 0x05, 0x10, 0x00, 0x08, 0xF0, 0xAB, 0xFE, 0x32, 0x46, 0x02, 0x23, 0x06, 0xA9, 0x10, 0x46, + 0x00, 0x94, 0x08, 0xF0, 0xB1, 0xFE, 0x31, 0x46, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0x00, 0x97, + 0x08, 0xF0, 0x8F, 0xFE, 0xE6, 0xE6, 0x2D, 0xE9, 0xF7, 0x4F, 0x8A, 0xB0, 0x00, 0x26, 0x05, 0x96, + 0x06, 0x96, 0x07, 0x96, 0x08, 0x96, 0x01, 0x24, 0x4F, 0xF0, 0x02, 0x09, 0x0D, 0xF1, 0x14, 0x0A, + 0x09, 0x96, 0xCD, 0xE9, 0x01, 0x4A, 0xCD, 0xE9, 0x03, 0x94, 0x07, 0x46, 0x07, 0xF1, 0x1C, 0x00, + 0x4D, 0x46, 0xFD, 0x4B, 0x4A, 0x46, 0x49, 0x46, 0x80, 0x46, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, + 0xA7, 0xFE, 0x07, 0xA8, 0xCD, 0xE9, 0x01, 0x50, 0xF7, 0x48, 0xCD, 0xE9, 0x03, 0x45, 0x43, 0x46, + 0x02, 0x22, 0x01, 0x21, 0x08, 0x38, 0x00, 0x95, 0x08, 0xF0, 0x9A, 0xFE, 0x0D, 0xF1, 0x24, 0x0B, + 0xCD, 0xE9, 0x01, 0x4B, 0x03, 0x94, 0xF0, 0x4B, 0x02, 0x22, 0x01, 0x21, 0x07, 0xA8, 0x00, 0x95, + 0x04, 0x94, 0x08, 0xF0, 0x8D, 0xFE, 0xEC, 0x4D, 0x18, 0x3D, 0x28, 0x78, 0x01, 0x28, 0x04, 0xD1, + 0x01, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0xA8, 0xFD, 0x68, 0x60, 0x09, 0x98, 0x69, 0x68, 0x4F, 0xF0, + 0x64, 0x08, 0x08, 0x44, 0x05, 0xA9, 0x09, 0x90, 0x01, 0x23, 0x02, 0x22, 0xCD, 0xF8, 0x00, 0x80, + 0x08, 0x46, 0x08, 0xF0, 0x4C, 0xFE, 0x09, 0x98, 0x00, 0x90, 0x01, 0x23, 0x02, 0x22, 0x05, 0xA8, + 0x0B, 0x99, 0x08, 0xF0, 0x36, 0xFE, 0x07, 0x96, 0x08, 0x96, 0x05, 0x96, 0x06, 0x96, 0x09, 0x96, + 0xCD, 0xE9, 0x01, 0x4A, 0xCD, 0xE9, 0x03, 0x94, 0x4E, 0x46, 0x02, 0x22, 0x07, 0xF1, 0x2C, 0x00, + 0xCD, 0xF8, 0x00, 0x90, 0xD4, 0x4B, 0x11, 0x46, 0x81, 0x46, 0x08, 0xF0, 0x59, 0xFE, 0x07, 0xA8, + 0xCD, 0xE9, 0x01, 0x60, 0xCD, 0xE9, 0x03, 0x46, 0xCF, 0x48, 0x4B, 0x46, 0x02, 0x22, 0x01, 0x21, + 0x08, 0x38, 0x00, 0x96, 0x08, 0xF0, 0x4C, 0xFE, 0xCD, 0xE9, 0x01, 0x4B, 0x03, 0x94, 0xCA, 0x4B, + 0x02, 0x22, 0x01, 0x21, 0x07, 0xA8, 0x00, 0x96, 0x04, 0x94, 0x08, 0xF0, 0x41, 0xFE, 0x28, 0x78, + 0x01, 0x28, 0x04, 0xD1, 0x00, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0x5E, 0xFD, 0x68, 0x60, 0x09, 0x98, + 0x69, 0x68, 0x01, 0x23, 0x08, 0x44, 0x05, 0xA9, 0x09, 0x90, 0x02, 0x22, 0xCD, 0xF8, 0x00, 0x80, + 0x08, 0x46, 0x08, 0xF0, 0x04, 0xFE, 0x09, 0x98, 0x00, 0x90, 0x01, 0x23, 0x02, 0x22, 0x05, 0xA8, + 0x0C, 0x99, 0x08, 0xF0, 0xEE, 0xFD, 0xE1, 0xE6, 0x2D, 0xE9, 0xF7, 0x4F, 0x8E, 0xB0, 0x00, 0x25, + 0x05, 0x95, 0x06, 0x95, 0x07, 0x95, 0x02, 0x24, 0x08, 0x95, 0x09, 0x95, 0x0A, 0x95, 0x0B, 0x95, + 0x05, 0xAF, 0x0C, 0x95, 0xCD, 0xE9, 0x01, 0x47, 0x8C, 0x46, 0x4F, 0xF0, 0x01, 0x0A, 0xAE, 0x4B, + 0x06, 0x46, 0x03, 0x94, 0x08, 0x3B, 0x52, 0x46, 0x21, 0x46, 0x60, 0x46, 0xCD, 0xF8, 0x00, 0xA0, + 0x04, 0x94, 0x08, 0xF0, 0x05, 0xFE, 0xA8, 0x48, 0x05, 0xAA, 0x02, 0x23, 0x11, 0x46, 0x28, 0x30, + 0x00, 0x94, 0x08, 0xF0, 0xEF, 0xFD, 0x0D, 0xF1, 0x24, 0x08, 0xCD, 0xE9, 0x01, 0x48, 0x06, 0xF1, + 0x1C, 0x03, 0x02, 0x22, 0x03, 0x94, 0x04, 0x94, 0x9B, 0x46, 0x11, 0x46, 0x05, 0xA8, 0x00, 0x94, + 0x08, 0xF0, 0xEE, 0xFD, 0x4F, 0xF0, 0x64, 0x09, 0x02, 0x23, 0x1A, 0x46, 0x59, 0x46, 0x09, 0xA8, + 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0xAD, 0xFD, 0x05, 0x95, 0x06, 0x95, 0x07, 0x95, 0x08, 0x95, + 0x09, 0x95, 0x0A, 0x95, 0x0B, 0x95, 0x0C, 0x95, 0xCD, 0xE9, 0x01, 0x47, 0x92, 0x4B, 0x03, 0x94, + 0x08, 0x3B, 0x01, 0x22, 0x02, 0x21, 0xCD, 0xF8, 0x00, 0xA0, 0x04, 0x94, 0x10, 0x98, 0x08, 0xF0, + 0xCF, 0xFD, 0x8D, 0x48, 0x05, 0xAA, 0x02, 0x23, 0x11, 0x46, 0x28, 0x30, 0x00, 0x94, 0x08, 0xF0, + 0xB9, 0xFD, 0xCD, 0xE9, 0x01, 0x48, 0x03, 0x94, 0x04, 0x94, 0x06, 0xF1, 0x2C, 0x03, 0x00, 0x94, + 0x02, 0x22, 0x1C, 0x46, 0x11, 0x46, 0x05, 0xA8, 0x08, 0xF0, 0xBA, 0xFD, 0x02, 0x23, 0x1A, 0x46, + 0x21, 0x46, 0x09, 0xA8, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0x7B, 0xFD, 0x11, 0xB0, 0xD2, 0xE5, + 0x38, 0xB5, 0x7E, 0x48, 0x7C, 0x4C, 0x01, 0x68, 0x18, 0x3C, 0x91, 0xF8, 0x80, 0x03, 0xC0, 0xF3, + 0x00, 0x12, 0x22, 0x70, 0xB1, 0xF8, 0xB1, 0x03, 0x1A, 0xB1, 0x64, 0x21, 0x48, 0x43, 0x0D, 0x46, + 0x01, 0xE0, 0xD1, 0xF8, 0xAD, 0x53, 0x74, 0x49, 0x80, 0x08, 0x02, 0x23, 0x48, 0x31, 0x00, 0x90, + 0x1A, 0x46, 0xA1, 0xF1, 0x10, 0x00, 0x08, 0xF0, 0x6A, 0xFD, 0x65, 0x60, 0x38, 0xBD, 0xF8, 0xB5, + 0x04, 0x46, 0x08, 0x68, 0x20, 0x60, 0x48, 0x68, 0x60, 0x60, 0x88, 0x68, 0xA0, 0x60, 0x00, 0x25, + 0x25, 0x64, 0xE5, 0x63, 0xB1, 0xF9, 0x02, 0x00, 0xC4, 0xE9, 0x03, 0x05, 0xB1, 0xF9, 0x00, 0x00, + 0xC4, 0xE9, 0x05, 0x05, 0x64, 0x48, 0x18, 0x38, 0x01, 0x78, 0x01, 0x29, 0x09, 0xD0, 0x60, 0x30, + 0x1C, 0x34, 0x0F, 0xC8, 0x0F, 0xC4, 0x84, 0xE8, 0x0F, 0x00, 0x2C, 0x3C, 0x84, 0xF8, 0x81, 0x50, + 0xF8, 0xBD, 0x50, 0x30, 0x1C, 0x34, 0x0F, 0xC8, 0x0F, 0xC4, 0x5C, 0x4E, 0x0F, 0xC4, 0x30, 0x68, + 0x64, 0x21, 0x02, 0x23, 0xB0, 0xF8, 0xB1, 0x03, 0x1A, 0x46, 0x48, 0x43, 0x80, 0x08, 0xA4, 0xF1, + 0x20, 0x01, 0x00, 0x90, 0x08, 0x46, 0x3C, 0x3C, 0x08, 0xF0, 0x31, 0xFD, 0x30, 0x68, 0x64, 0x21, + 0x02, 0x23, 0xB0, 0xF8, 0xB1, 0x03, 0x1A, 0x46, 0x48, 0x43, 0x80, 0x08, 0x04, 0xF1, 0x2C, 0x01, + 0x00, 0x90, 0x08, 0x46, 0x08, 0xF0, 0x23, 0xFD, 0x94, 0xE8, 0x07, 0x00, 0x04, 0xF1, 0x44, 0x03, + 0x83, 0xE8, 0x07, 0x00, 0x84, 0xF8, 0x80, 0x50, 0xD0, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x03, 0x22, + 0x08, 0xF0, 0xB0, 0xFD, 0x20, 0x46, 0xFF, 0xF7, 0x94, 0xFC, 0xB4, 0xF9, 0x02, 0x00, 0xE0, 0x60, + 0xB4, 0xF9, 0x06, 0x10, 0x40, 0x1A, 0x20, 0x61, 0xB4, 0xF9, 0x00, 0x00, 0x60, 0x61, 0xB4, 0xF9, + 0x04, 0x10, 0x40, 0x1A, 0xA0, 0x61, 0x10, 0xBD, 0x7F, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x03, 0x22, + 0x08, 0xF0, 0x98, 0xFD, 0x20, 0x46, 0xFF, 0xF7, 0x7C, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0xD9, 0xFC, + 0x20, 0x46, 0xFF, 0xF7, 0x4C, 0xFD, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, + 0x02, 0xAA, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x4E, 0xFE, 0x02, 0xAA, 0x69, 0x46, 0x20, 0x46, + 0xFF, 0xF7, 0xCE, 0xFD, 0x02, 0xAA, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFE, 0xA0, 0x89, + 0x68, 0x80, 0xA0, 0x8A, 0x28, 0x80, 0x28, 0x48, 0x18, 0x38, 0x00, 0x78, 0x01, 0x28, 0x05, 0xD1, + 0x03, 0x22, 0x29, 0x46, 0x04, 0xF1, 0x44, 0x00, 0x08, 0xF0, 0x6C, 0xFD, 0x7F, 0xBD, 0x2D, 0xE9, + 0xF0, 0x47, 0x06, 0x46, 0x48, 0x88, 0xB6, 0xF8, 0x4A, 0x30, 0x89, 0x46, 0xC0, 0x1A, 0xB6, 0xF8, + 0x46, 0x40, 0x92, 0x46, 0x01, 0xB2, 0xB9, 0xF8, 0x00, 0x00, 0xB6, 0xF8, 0x48, 0x20, 0xE3, 0x1A, + 0x1C, 0xB2, 0x80, 0x1A, 0xB6, 0xF8, 0x44, 0x30, 0x00, 0xB2, 0x9A, 0x1A, 0x15, 0xB2, 0x0C, 0xB9, + 0x00, 0x2D, 0x27, 0xD0, 0x49, 0x43, 0x00, 0xFB, 0x00, 0x10, 0x64, 0x21, 0x48, 0x43, 0x04, 0xFB, + 0x04, 0xF1, 0x05, 0xFB, 0x05, 0x11, 0xB0, 0xFB, 0xF1, 0xF0, 0x08, 0xF0, 0x83, 0xFC, 0x44, 0x43, + 0x0A, 0x22, 0x45, 0x43, 0x21, 0xB2, 0x28, 0xB2, 0x91, 0xFB, 0xF2, 0xF1, 0x90, 0xFB, 0xF2, 0xF0, + 0xB6, 0xF8, 0x46, 0x20, 0x61, 0xF3, 0x1F, 0x48, 0x11, 0x44, 0x61, 0xF3, 0x1F, 0x47, 0xB6, 0xF8, + 0x44, 0x10, 0x60, 0xF3, 0x0F, 0x08, 0x08, 0x44, 0x60, 0xF3, 0x0F, 0x07, 0xC9, 0xF8, 0x00, 0x70, + 0xCA, 0xF8, 0x00, 0x80, 0xBD, 0xE8, 0xF0, 0x87, 0x88, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xF0, 0xB5, 0x4F, 0xF0, 0x00, 0x0C, 0x63, 0x46, 0x65, 0x46, 0x14, 0x46, 0x07, 0xE0, 0x00, 0xBF, + 0x01, 0xEB, 0xC4, 0x06, 0x76, 0x68, 0x35, 0x44, 0x51, 0xF8, 0x34, 0x60, 0x33, 0x44, 0x64, 0x1E, + 0xF6, 0xD2, 0x95, 0xFB, 0xF2, 0xF6, 0x93, 0xFB, 0xF2, 0xF7, 0xC0, 0xF8, 0x04, 0xC0, 0x15, 0x46, + 0x42, 0xF2, 0x10, 0x74, 0xC0, 0xF8, 0x00, 0xC0, 0x17, 0xE0, 0x00, 0xBF, 0x01, 0xEB, 0xC5, 0x03, + 0x5B, 0x68, 0x9B, 0x1B, 0x5B, 0x43, 0xA3, 0x42, 0x00, 0xDD, 0x23, 0x46, 0xD0, 0xF8, 0x04, 0xC0, + 0x63, 0x44, 0x43, 0x60, 0x51, 0xF8, 0x35, 0x30, 0xDB, 0x1B, 0x5B, 0x43, 0xA3, 0x42, 0x00, 0xDD, + 0x23, 0x46, 0xD0, 0xF8, 0x00, 0xC0, 0x63, 0x44, 0x03, 0x60, 0x6D, 0x1E, 0xE6, 0xD2, 0x41, 0x68, + 0x64, 0x23, 0x59, 0x43, 0x91, 0xFB, 0xF2, 0xF1, 0x41, 0x60, 0x01, 0x68, 0x59, 0x43, 0x91, 0xFB, + 0xF2, 0xF1, 0x01, 0x60, 0xF0, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x14, 0x21, 0x53, 0x48, 0x0D, 0xF0, + 0x82, 0xFF, 0x0D, 0xF0, 0x24, 0xFD, 0x64, 0x21, 0x48, 0x43, 0x50, 0x49, 0x08, 0x60, 0x10, 0xBD, + 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x38, 0x81, 0x04, 0x46, 0x0D, 0x46, 0xD8, 0xF8, 0x00, 0x00, + 0x90, 0xF8, 0xA0, 0x03, 0x00, 0xF0, 0x0F, 0x06, 0xC6, 0xF1, 0x10, 0x07, 0x20, 0x46, 0x00, 0xF0, + 0x5C, 0xF8, 0xF0, 0xB1, 0xE0, 0x89, 0x61, 0x8A, 0x22, 0x8A, 0x40, 0x1A, 0xA1, 0x89, 0x00, 0xB2, + 0x89, 0x1A, 0xB4, 0xF9, 0x2A, 0x20, 0x78, 0x43, 0x02, 0xFB, 0x06, 0x00, 0x00, 0x11, 0x60, 0x85, + 0x09, 0xB2, 0xB4, 0xF9, 0x28, 0x00, 0x79, 0x43, 0x00, 0xFB, 0x06, 0x10, 0x00, 0x11, 0x20, 0x85, + 0x0D, 0xF0, 0xDF, 0xFB, 0x39, 0x4A, 0x91, 0x89, 0x08, 0x1A, 0x11, 0x7C, 0x01, 0x29, 0x0E, 0xD0, + 0x0F, 0xE0, 0x20, 0x6B, 0x02, 0x28, 0x07, 0xD1, 0xE0, 0x89, 0x61, 0x8A, 0x40, 0x1A, 0x60, 0x85, + 0xA0, 0x89, 0x21, 0x8A, 0x40, 0x1A, 0x20, 0x85, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x51, 0x68, + 0x08, 0x44, 0x00, 0x28, 0x00, 0xDA, 0x00, 0x20, 0x00, 0xEB, 0x80, 0x01, 0x16, 0x68, 0x49, 0x00, + 0xB1, 0xFB, 0xF6, 0xF7, 0xD8, 0xF8, 0x00, 0x10, 0xB1, 0xF8, 0xA1, 0x33, 0x9F, 0x42, 0x03, 0xD9, + 0x73, 0x43, 0x0A, 0x20, 0xB3, 0xFB, 0xF0, 0xF0, 0xB4, 0xF9, 0x2A, 0x60, 0x91, 0xF8, 0xA3, 0x33, + 0x92, 0x68, 0x5E, 0x43, 0x64, 0x21, 0x46, 0x43, 0x4A, 0x43, 0xB4, 0xF9, 0x28, 0x40, 0x96, 0xFB, + 0xF2, 0xF1, 0x5C, 0x43, 0x44, 0x43, 0x94, 0xFB, 0xF2, 0xF0, 0x6A, 0x88, 0x11, 0x44, 0x69, 0x80, + 0x29, 0x88, 0x08, 0x44, 0x28, 0x80, 0x01, 0x20, 0xCF, 0xE7, 0x70, 0xB5, 0x04, 0x46, 0x18, 0x48, + 0x01, 0x25, 0x00, 0x68, 0x90, 0xF8, 0x80, 0x03, 0x80, 0x07, 0x12, 0xD5, 0xB4, 0xF8, 0x42, 0x00, + 0x01, 0x07, 0x0E, 0xD4, 0x00, 0x06, 0x0C, 0xD4, 0x0D, 0xF0, 0xAE, 0xFF, 0x48, 0xB9, 0x11, 0x48, + 0x00, 0x78, 0x30, 0xB9, 0x10, 0x48, 0x00, 0x78, 0x18, 0xB9, 0x10, 0x48, 0x00, 0x78, 0x01, 0x28, + 0x02, 0xD9, 0x00, 0x20, 0x20, 0x63, 0x0E, 0xE0, 0x20, 0x6B, 0x02, 0x28, 0x0C, 0xD8, 0x40, 0x1C, + 0x20, 0x63, 0x02, 0x28, 0x07, 0xD9, 0x94, 0xF8, 0x3E, 0x01, 0x04, 0x28, 0x04, 0xD0, 0x06, 0x28, + 0x02, 0xD0, 0x07, 0x28, 0x00, 0xD0, 0x00, 0x25, 0x28, 0x46, 0x70, 0xBD, 0xC8, 0x24, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xF3, 0x06, 0x10, 0x00, + 0xB0, 0xF8, 0x44, 0x20, 0xB1, 0xF8, 0x44, 0x30, 0x1A, 0x44, 0xA0, 0xF8, 0x44, 0x20, 0xB0, 0xF8, + 0x46, 0x20, 0xB1, 0xF8, 0x46, 0x30, 0x1A, 0x44, 0xA0, 0xF8, 0x46, 0x20, 0x42, 0x6B, 0x4B, 0x6B, + 0x1A, 0x44, 0x42, 0x63, 0x82, 0x6B, 0x8B, 0x6B, 0x1A, 0x44, 0x82, 0x63, 0xB1, 0xF9, 0x54, 0x20, + 0xB0, 0xF9, 0x54, 0x30, 0x9A, 0x42, 0x01, 0xDD, 0xA0, 0xF8, 0x54, 0x20, 0xB1, 0xF9, 0x56, 0x20, + 0xB0, 0xF9, 0x56, 0x30, 0x9A, 0x42, 0x01, 0xDD, 0xA0, 0xF8, 0x56, 0x20, 0x90, 0xF8, 0x44, 0x21, + 0x91, 0xF8, 0x44, 0x31, 0x9A, 0x42, 0x0A, 0xD0, 0x30, 0xF8, 0x48, 0x2F, 0xB1, 0xF8, 0x48, 0x30, + 0x1A, 0x44, 0x20, 0xF8, 0x0C, 0x29, 0xC9, 0x6B, 0x02, 0x68, 0x11, 0x44, 0x01, 0x60, 0x70, 0x47, + 0x2D, 0xE9, 0xF0, 0x4F, 0x97, 0xB0, 0x80, 0x46, 0x00, 0xF5, 0x80, 0x50, 0x00, 0x26, 0x11, 0x90, + 0xBF, 0xE0, 0x00, 0x20, 0x08, 0x90, 0x05, 0x90, 0x10, 0x90, 0x12, 0x90, 0x81, 0x46, 0x82, 0x46, + 0x83, 0x46, 0x05, 0x46, 0x07, 0x46, 0x0A, 0x90, 0x0B, 0x90, 0x0C, 0x90, 0x0D, 0x90, 0x08, 0xEB, + 0x86, 0x00, 0x00, 0xF5, 0x80, 0x50, 0x14, 0x90, 0xD0, 0xF8, 0x2C, 0x04, 0x0A, 0xAA, 0x04, 0x46, + 0x17, 0xE0, 0x00, 0xBF, 0x90, 0xF8, 0x44, 0x11, 0x08, 0xEB, 0x01, 0x0C, 0x53, 0x5C, 0x0C, 0xF5, + 0x80, 0x5C, 0x5B, 0x1C, 0xDB, 0xB2, 0x53, 0x54, 0x9C, 0xF8, 0x1A, 0xC4, 0x63, 0x45, 0x06, 0xD1, + 0x01, 0x2B, 0x04, 0xD9, 0x01, 0x23, 0x8B, 0x40, 0x12, 0x99, 0x0B, 0x43, 0x12, 0x93, 0xD0, 0xF8, + 0x4C, 0x01, 0x00, 0x28, 0xE6, 0xD1, 0x40, 0xE0, 0x94, 0xF8, 0x44, 0x11, 0x01, 0x20, 0x00, 0xFA, + 0x01, 0xFC, 0x12, 0x99, 0x1C, 0xEA, 0x01, 0x0F, 0x12, 0xD1, 0xA0, 0x6B, 0xB4, 0xF9, 0x0E, 0x30, + 0x05, 0x9A, 0x49, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x05, 0x92, 0x89, 0x46, 0xB4, 0xF9, 0x0C, 0x30, + 0x51, 0x46, 0x5A, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x8A, 0x46, 0x93, 0x46, 0x05, 0x44, 0x19, 0xE0, + 0x08, 0x99, 0x1C, 0xEA, 0x01, 0x0F, 0x15, 0xD1, 0xE0, 0x6B, 0xB4, 0xF9, 0x1E, 0x30, 0x05, 0x9A, + 0x49, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x05, 0x92, 0x89, 0x46, 0xB4, 0xF9, 0x1C, 0x30, 0x51, 0x46, + 0x5A, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x8A, 0x46, 0x08, 0x99, 0x05, 0x44, 0x4C, 0xEA, 0x01, 0x00, + 0x93, 0x46, 0x08, 0x90, 0x20, 0x46, 0x00, 0xF0, 0xFA, 0xFC, 0x01, 0x28, 0x02, 0xD1, 0x10, 0x98, + 0x40, 0x1C, 0x10, 0x90, 0xD4, 0xF8, 0x4C, 0x41, 0x7F, 0x1C, 0x00, 0x2C, 0xBC, 0xD1, 0x00, 0x2F, + 0x45, 0xDD, 0xE8, 0x17, 0x04, 0x46, 0x03, 0x46, 0x2A, 0x46, 0x48, 0x46, 0x05, 0x99, 0x0D, 0xF0, + 0x4D, 0xFD, 0xAD, 0xF8, 0x1E, 0x00, 0x2A, 0x46, 0x23, 0x46, 0x50, 0x46, 0x59, 0x46, 0x0D, 0xF0, + 0x45, 0xFD, 0xAD, 0xF8, 0x1C, 0x00, 0x14, 0x98, 0x4F, 0xF0, 0xFF, 0x37, 0x00, 0x25, 0xD0, 0xF8, + 0x2C, 0x44, 0x23, 0xE0, 0x20, 0x46, 0x00, 0xF0, 0xD2, 0xFC, 0x01, 0x28, 0x01, 0xD0, 0x10, 0x98, + 0x90, 0xB9, 0x04, 0xF1, 0x10, 0x01, 0x07, 0xA8, 0x08, 0xF0, 0x7B, 0xFB, 0xB8, 0x42, 0x0B, 0xD2, + 0x07, 0x46, 0x3D, 0xB1, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x1A, 0xFF, 0x29, 0x46, 0x40, 0x46, + 0x00, 0xF0, 0xD4, 0xFC, 0x25, 0x46, 0x07, 0xE0, 0x21, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x10, 0xFF, + 0x21, 0x46, 0x40, 0x46, 0x00, 0xF0, 0xCA, 0xFC, 0xD4, 0xF8, 0x4C, 0x41, 0x00, 0x2C, 0xD9, 0xD1, + 0x07, 0x98, 0x45, 0xF8, 0x0C, 0x0F, 0xE8, 0x8E, 0x40, 0xF0, 0x40, 0x00, 0xE8, 0x86, 0x11, 0x98, + 0x76, 0x1C, 0x90, 0xF8, 0xA4, 0x04, 0xB0, 0x42, 0x3F, 0xF7, 0x3B, 0xAF, 0x17, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0x2D, 0xE9, 0xF7, 0x4F, 0x05, 0x46, 0x0E, 0x46, 0xC1, 0xEB, 0xC6, 0x00, 0x00, 0xEB, + 0x40, 0x00, 0x82, 0xB0, 0x05, 0xEB, 0x00, 0x1A, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0xDF, 0xF8, + 0x98, 0xB5, 0x05, 0xF5, 0x80, 0x57, 0x7F, 0xE0, 0xD7, 0xF8, 0xB0, 0x23, 0x08, 0xFA, 0x04, 0xF9, + 0x12, 0xEA, 0x09, 0x0F, 0x77, 0xD0, 0xB4, 0x42, 0x75, 0xD0, 0xDB, 0xF8, 0x0C, 0x10, 0x31, 0xF8, + 0x16, 0x10, 0x11, 0xEA, 0x09, 0x0F, 0x6E, 0xD1, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, + 0x05, 0xEB, 0x00, 0x10, 0x00, 0x90, 0x00, 0xF0, 0x6C, 0xFC, 0x01, 0x28, 0x04, 0xD0, 0x00, 0x98, + 0x00, 0xF0, 0x6D, 0xFC, 0x01, 0x28, 0x5E, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x5A, 0xFC, 0xE8, 0xBB, + 0x00, 0x99, 0x0A, 0xF1, 0x0C, 0x00, 0x0C, 0x31, 0x08, 0xF0, 0x13, 0xFB, 0x01, 0x90, 0xDB, 0xF8, + 0x0C, 0x00, 0x08, 0xFA, 0x06, 0xF2, 0x30, 0xF8, 0x16, 0x30, 0x43, 0xEA, 0x09, 0x03, 0x20, 0xF8, + 0x16, 0x30, 0x30, 0xF8, 0x14, 0x30, 0x13, 0x43, 0x20, 0xF8, 0x14, 0x30, 0x50, 0x46, 0xDB, 0xF8, + 0x04, 0x90, 0x00, 0xF0, 0x58, 0xFC, 0x01, 0x28, 0x04, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x41, 0xFC, + 0x01, 0x28, 0x1D, 0xD0, 0x50, 0x46, 0x00, 0xF0, 0x3C, 0xFC, 0x01, 0x28, 0x04, 0xD1, 0x00, 0x98, + 0x00, 0xF0, 0x49, 0xFC, 0x01, 0x28, 0x13, 0xD0, 0x50, 0x46, 0x00, 0xF0, 0x32, 0xFC, 0x01, 0x28, + 0x1E, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x2D, 0xFC, 0x01, 0x28, 0x19, 0xD1, 0x00, 0x99, 0x9A, 0xF8, + 0x42, 0x00, 0x91, 0xF8, 0x42, 0x10, 0x08, 0x43, 0x80, 0x06, 0x00, 0xE0, 0x1B, 0xE0, 0x0F, 0xD5, + 0xBA, 0xF8, 0x42, 0x00, 0xDB, 0xF8, 0x08, 0x90, 0x40, 0xF0, 0x20, 0x01, 0xAA, 0xF8, 0x42, 0x10, + 0x00, 0x98, 0xB0, 0xF8, 0x42, 0x00, 0x40, 0xF0, 0x20, 0x01, 0x00, 0x98, 0xA0, 0xF8, 0x42, 0x10, + 0x01, 0x98, 0x48, 0x45, 0x07, 0xD2, 0x41, 0xF2, 0x2C, 0x40, 0x51, 0x46, 0x28, 0x44, 0x04, 0x9B, + 0x00, 0x9A, 0x00, 0xF0, 0x32, 0xFC, 0x64, 0x1C, 0x97, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0xBF, 0xF6, + 0x7B, 0xAF, 0x05, 0xB0, 0x63, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0x88, 0x46, 0x06, 0x46, 0xC1, 0xEB, + 0xC8, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x14, 0xDF, 0xF8, 0x6C, 0xA4, 0x94, 0xF8, + 0x42, 0x00, 0x4F, 0xF0, 0x04, 0x0B, 0x40, 0x06, 0x4F, 0xF0, 0x01, 0x09, 0x06, 0xF5, 0x80, 0x55, + 0x2E, 0xD5, 0x00, 0x27, 0x04, 0xF1, 0x0C, 0x0B, 0x24, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, + 0x09, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x1C, 0xD0, 0x47, 0x45, 0x1A, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, + 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x10, 0x00, 0x90, 0x00, 0xF0, 0xD2, 0xFB, 0x01, 0x28, + 0x0F, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0xC5, 0xFB, 0x58, 0xB9, 0x00, 0x99, 0x58, 0x46, 0x10, 0x31, + 0x08, 0xF0, 0x7F, 0xFA, 0xDA, 0xF8, 0x08, 0x10, 0x88, 0x42, 0x02, 0xD2, 0x04, 0x20, 0x84, 0xF8, + 0x3E, 0x01, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xD7, 0xDA, 0xBD, 0xE8, 0xF8, 0x8F, + 0xFE, 0x49, 0xE0, 0x6A, 0x09, 0x68, 0x91, 0xF8, 0x95, 0x13, 0x88, 0x42, 0xF6, 0xD9, 0x00, 0x27, + 0x31, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, 0x09, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x29, 0xD0, + 0x47, 0x45, 0x27, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x10, + 0x00, 0x90, 0x00, 0xF0, 0x9E, 0xFB, 0x01, 0x28, 0x1C, 0xD1, 0x00, 0x98, 0x94, 0xF8, 0x44, 0x11, + 0x90, 0xF8, 0x45, 0x01, 0x81, 0x42, 0x15, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x8A, 0xFB, 0x88, 0xB9, + 0x00, 0x99, 0x04, 0xF1, 0x0C, 0x00, 0x10, 0x31, 0x08, 0xF0, 0x43, 0xFA, 0xDA, 0xF8, 0x08, 0x10, + 0x88, 0x42, 0x07, 0xD2, 0x84, 0xF8, 0x3E, 0xB1, 0xB4, 0xF8, 0x42, 0x00, 0x40, 0xF0, 0x40, 0x00, + 0xA4, 0xF8, 0x42, 0x00, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xCA, 0xDA, 0x00, 0x27, + 0x28, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, 0x09, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x20, 0xD0, + 0x47, 0x45, 0x1E, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x10, + 0x83, 0x46, 0x00, 0xF0, 0x6C, 0xFB, 0x01, 0x28, 0x13, 0xD1, 0x58, 0x46, 0x00, 0xF0, 0x59, 0xFB, + 0x78, 0xB9, 0x0B, 0xF1, 0x10, 0x01, 0x04, 0xF1, 0x0C, 0x00, 0x08, 0xF0, 0x12, 0xFA, 0xDA, 0xF8, + 0x08, 0x10, 0x88, 0x42, 0x05, 0xD2, 0xBB, 0xF8, 0x42, 0x00, 0x40, 0xF0, 0x40, 0x01, 0xAB, 0xF8, + 0x42, 0x10, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xD3, 0xDA, 0x8E, 0xE7, 0x2D, 0xE9, + 0xF8, 0x43, 0x06, 0x46, 0xFF, 0x20, 0x00, 0x25, 0x8D, 0xF8, 0x00, 0x00, 0x01, 0x27, 0x06, 0xF5, + 0x80, 0x54, 0x19, 0xE0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x18, + 0xD4, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x05, 0xF1, 0x08, 0x42, 0x0C, 0xD0, 0x40, 0x46, 0x00, 0xF0, + 0x28, 0xFB, 0x01, 0x28, 0x07, 0xD0, 0x98, 0xF8, 0x3E, 0x01, 0x05, 0x28, 0x03, 0xD1, 0x29, 0x46, + 0x30, 0x46, 0xFF, 0xF7, 0x28, 0xFF, 0x6D, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0xE1, 0xDA, + 0x00, 0x25, 0x1B, 0xE0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x18, + 0xD4, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x05, 0xF1, 0x08, 0x42, 0x0E, 0xD0, 0x40, 0x46, 0x00, 0xF0, + 0x08, 0xFB, 0x01, 0x28, 0x09, 0xD0, 0x40, 0x46, 0x00, 0xF0, 0x11, 0xFB, 0x01, 0x28, 0x04, 0xD1, + 0x6A, 0x46, 0x29, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x6C, 0xFE, 0x6D, 0x1C, 0x94, 0xF9, 0xB8, 0x03, + 0xA8, 0x42, 0xDF, 0xDA, 0x00, 0x25, 0xB8, 0x46, 0x21, 0xE0, 0x00, 0xBF, 0xC5, 0xEB, 0xC5, 0x00, + 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x17, 0xD4, 0xF8, 0xB0, 0x13, 0x08, 0xFA, 0x05, 0xF0, + 0x01, 0x42, 0x13, 0xD0, 0x38, 0x46, 0x00, 0xF0, 0xE4, 0xFA, 0x01, 0x28, 0x0E, 0xD0, 0x38, 0x46, + 0x00, 0xF0, 0xE7, 0xFA, 0x01, 0x28, 0x04, 0xD1, 0x6A, 0x46, 0x29, 0x46, 0x30, 0x46, 0xFF, 0xF7, + 0x48, 0xFE, 0x37, 0xF8, 0x42, 0x0F, 0x20, 0xF0, 0x20, 0x00, 0x38, 0x80, 0x6D, 0x1C, 0x94, 0xF9, + 0xB8, 0x03, 0xA8, 0x42, 0xDA, 0xDA, 0x9D, 0xF8, 0x00, 0x00, 0x40, 0x1C, 0x84, 0xF8, 0xA4, 0x04, + 0xBD, 0xE8, 0xF8, 0x83, 0x10, 0xB5, 0x04, 0x46, 0x87, 0x48, 0x03, 0x21, 0x0C, 0x30, 0x05, 0xF0, + 0x97, 0xFB, 0x85, 0x48, 0x1E, 0x21, 0xC0, 0x68, 0x0D, 0xF0, 0xD3, 0xFB, 0x41, 0xF2, 0x2C, 0x40, + 0x7C, 0x21, 0x20, 0x44, 0x0D, 0xF0, 0xEF, 0xFB, 0x80, 0x48, 0x02, 0x68, 0x80, 0x48, 0xB2, 0xF8, + 0x96, 0x13, 0x80, 0x79, 0x49, 0x43, 0x10, 0xB1, 0xB2, 0xF8, 0x6C, 0x13, 0x49, 0x43, 0xB2, 0xF8, + 0x98, 0x23, 0x02, 0xFB, 0x02, 0x10, 0x78, 0x4A, 0x12, 0x1D, 0x11, 0x60, 0x11, 0x1D, 0x08, 0x60, + 0x20, 0x46, 0xFF, 0xF7, 0x5C, 0xFF, 0x20, 0x46, 0xFF, 0xF7, 0x3A, 0xFD, 0x72, 0x48, 0x03, 0x21, + 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x30, 0x05, 0xF0, 0x83, 0xBB, 0xF0, 0xB4, 0x84, 0x6B, 0xC2, 0x68, + 0x8B, 0x6B, 0xCE, 0x68, 0x17, 0x14, 0x67, 0x43, 0x4F, 0xEA, 0x26, 0x4C, 0x03, 0xFB, 0x0C, 0x77, + 0xE5, 0x18, 0x97, 0xFB, 0xF5, 0xF7, 0x67, 0xF3, 0x1F, 0x42, 0x17, 0xB2, 0x67, 0x43, 0x34, 0xB2, + 0x03, 0xFB, 0x04, 0x73, 0x93, 0xFB, 0xF5, 0xF3, 0x63, 0xF3, 0x0F, 0x02, 0xC2, 0x60, 0xF0, 0xBC, + 0xDE, 0xE4, 0x62, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x40, 0x24, 0x92, 0x06, 0x11, 0xD5, 0x90, 0xF8, + 0x47, 0x31, 0x23, 0xB1, 0x91, 0xF8, 0x47, 0x21, 0x0A, 0xB1, 0x93, 0x42, 0x07, 0xD1, 0x90, 0xF8, + 0x48, 0x01, 0x30, 0xB1, 0x91, 0xF8, 0x48, 0x11, 0x19, 0xB1, 0x88, 0x42, 0x01, 0xD0, 0x00, 0x20, + 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xFC, 0x5F, 0x00, 0xF5, 0x80, 0x54, 0x05, 0x46, + 0xD4, 0xF8, 0xBC, 0x13, 0xD4, 0xF8, 0xB0, 0x03, 0x01, 0x40, 0x00, 0x28, 0xC4, 0xF8, 0xBC, 0x13, + 0x4F, 0xF0, 0x00, 0x00, 0x0A, 0xD0, 0x81, 0x46, 0x0F, 0x21, 0x4E, 0x48, 0x0D, 0xF0, 0x83, 0xFB, + 0x00, 0x26, 0xDF, 0xF8, 0x30, 0xA1, 0x4F, 0xF0, 0x01, 0x08, 0x5B, 0xE0, 0xC4, 0xF8, 0xBC, 0x03, + 0xBD, 0xE8, 0xFC, 0x9F, 0xD4, 0xF8, 0xB0, 0x13, 0x08, 0xFA, 0x06, 0xF2, 0x40, 0x46, 0x11, 0x42, + 0x4F, 0xD0, 0xC6, 0xEB, 0xC6, 0x01, 0x01, 0xEB, 0x41, 0x01, 0x05, 0xEB, 0x01, 0x11, 0x91, 0xF8, + 0x40, 0x30, 0x1B, 0x06, 0xD4, 0xF8, 0xBC, 0x33, 0x11, 0xD5, 0x13, 0x43, 0x05, 0xEB, 0x86, 0x02, + 0xC4, 0xF8, 0xBC, 0x33, 0x02, 0xF5, 0x9C, 0x52, 0xD1, 0xF8, 0x5A, 0x30, 0x13, 0x64, 0x91, 0xF8, + 0x44, 0x11, 0x88, 0x40, 0x40, 0xEA, 0x09, 0x09, 0x0A, 0xF8, 0x01, 0x60, 0x31, 0xE0, 0x13, 0x42, + 0x2F, 0xD0, 0x91, 0xF8, 0x3E, 0x31, 0x06, 0x2B, 0x15, 0xD0, 0x05, 0x2B, 0x13, 0xD0, 0x91, 0xF8, + 0x44, 0x21, 0x08, 0xFA, 0x02, 0xF0, 0x40, 0xEA, 0x09, 0x09, 0x0A, 0xF8, 0x02, 0x60, 0x00, 0xBF, + 0x05, 0xEB, 0x86, 0x07, 0x5A, 0x31, 0x07, 0xF5, 0x9E, 0x57, 0x8B, 0x46, 0x38, 0x46, 0x03, 0xF0, + 0x15, 0xFA, 0x98, 0xB1, 0x15, 0xE0, 0xB1, 0xF8, 0x42, 0x00, 0x20, 0xF0, 0x08, 0x00, 0xA1, 0xF8, + 0x42, 0x00, 0xD4, 0xF8, 0xBC, 0x03, 0x90, 0x43, 0xC4, 0xF8, 0xBC, 0x03, 0x22, 0x4A, 0x05, 0xEB, + 0x86, 0x00, 0x00, 0xF5, 0x9C, 0x50, 0x12, 0x68, 0x02, 0x64, 0xE1, 0xE7, 0xDB, 0xF8, 0x00, 0x00, + 0x38, 0x60, 0x76, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xB0, 0x42, 0xA3, 0xDA, 0x00, 0x27, 0x71, 0xE0, + 0xD4, 0xF8, 0xB0, 0x23, 0x08, 0xFA, 0x07, 0xF1, 0x40, 0x46, 0x0A, 0x42, 0x69, 0xD0, 0xD4, 0xF8, + 0xBC, 0x23, 0x0A, 0x42, 0x65, 0xD1, 0xC7, 0xEB, 0xC7, 0x01, 0x01, 0xEB, 0x41, 0x01, 0x05, 0xEB, + 0x01, 0x1B, 0x9B, 0xF8, 0x3E, 0x11, 0x02, 0x29, 0x01, 0xD0, 0x01, 0x29, 0x59, 0xD1, 0x9B, 0xF8, + 0x44, 0x11, 0x00, 0xFA, 0x01, 0xF2, 0x12, 0xEA, 0x09, 0x0F, 0x24, 0xD0, 0x1A, 0xF8, 0x01, 0x00, + 0xB8, 0x42, 0x4E, 0xD0, 0xC0, 0xEB, 0xC0, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x05, 0xEB, 0x00, 0x16, + 0x30, 0x46, 0x59, 0x46, 0x0A, 0xE0, 0x00, 0x00, 0xE0, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xEC, 0x06, 0x10, 0x00, 0x70, 0x25, 0x10, 0x00, 0x52, 0x6C, 0x01, 0x00, 0xFF, 0xF7, 0x31, 0xFF, + 0x01, 0x28, 0x36, 0xD1, 0x30, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0x0F, 0xFF, 0x59, 0x46, 0x28, 0x46, + 0x00, 0xF0, 0xA0, 0xFF, 0x2D, 0xE0, 0x0B, 0xF1, 0x5A, 0x01, 0x00, 0x26, 0x01, 0x91, 0x24, 0xE0, + 0xD4, 0xF8, 0xBC, 0x13, 0x08, 0xFA, 0x06, 0xF0, 0x01, 0x42, 0x1D, 0xD0, 0xC6, 0xEB, 0xC6, 0x00, + 0x00, 0xEB, 0x40, 0x00, 0x05, 0xEB, 0x00, 0x10, 0x05, 0xEB, 0x86, 0x01, 0x00, 0x90, 0x01, 0xF5, + 0x9E, 0x51, 0x01, 0x98, 0x03, 0xF0, 0x9A, 0xF9, 0x01, 0x28, 0x0D, 0xD1, 0x59, 0x46, 0x00, 0x98, + 0xFF, 0xF7, 0x07, 0xFF, 0x01, 0x28, 0x07, 0xD1, 0x59, 0x46, 0x00, 0x98, 0xFF, 0xF7, 0xE5, 0xFE, + 0x59, 0x46, 0x28, 0x46, 0x00, 0xF0, 0x76, 0xFF, 0x76, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xB0, 0x42, + 0xD6, 0xDA, 0x7F, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0x89, 0xDA, 0x28, 0xE7, 0x2D, 0xE9, + 0xF0, 0x47, 0x04, 0x46, 0x91, 0x42, 0x56, 0xD0, 0x07, 0xD9, 0x01, 0xEB, 0x02, 0x00, 0xA0, 0xEB, + 0x02, 0x01, 0xCA, 0xB2, 0xA0, 0xEB, 0x02, 0x00, 0xC1, 0xB2, 0x01, 0xEB, 0xC1, 0x00, 0x04, 0xEB, + 0xC0, 0x01, 0x02, 0xEB, 0xC2, 0x00, 0x04, 0xEB, 0xC0, 0x00, 0xB1, 0xF9, 0x32, 0x50, 0xB0, 0xF9, + 0x32, 0x30, 0x81, 0x46, 0x9D, 0x42, 0x00, 0xDA, 0x4B, 0x86, 0xCB, 0x8C, 0xC5, 0x8C, 0x2B, 0x44, + 0xCB, 0x84, 0x0B, 0x8D, 0x05, 0x8D, 0x2B, 0x44, 0x0B, 0x85, 0x8B, 0x69, 0x85, 0x69, 0x2B, 0x44, + 0x8B, 0x61, 0xC7, 0x69, 0xCE, 0x69, 0xCB, 0x68, 0xD9, 0xF8, 0x0C, 0x00, 0x4F, 0xEA, 0x23, 0x4C, + 0x4F, 0xEA, 0x20, 0x48, 0x0C, 0xFB, 0x06, 0xFC, 0xF5, 0x19, 0x07, 0xFB, 0x08, 0xCC, 0x9C, 0xFB, + 0xF5, 0xFC, 0x6C, 0xF3, 0x1F, 0x43, 0x0F, 0xFA, 0x83, 0xFC, 0x0C, 0xFB, 0x06, 0xFC, 0x00, 0xB2, + 0x07, 0xFB, 0x00, 0xC0, 0x90, 0xFB, 0xF5, 0xF0, 0x60, 0xF3, 0x0F, 0x03, 0xCD, 0x61, 0xCB, 0x60, + 0x94, 0xF8, 0x38, 0x04, 0x41, 0x1E, 0x91, 0x42, 0x08, 0xD0, 0x00, 0xEB, 0xC0, 0x00, 0x04, 0xEB, + 0xC0, 0x01, 0x48, 0x46, 0x48, 0x22, 0x48, 0x39, 0x0D, 0xF0, 0xF1, 0xF9, 0x94, 0xF8, 0x38, 0x04, + 0x40, 0x1E, 0x84, 0xF8, 0x38, 0x04, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x5F, 0x16, 0x46, + 0x0F, 0x46, 0x82, 0x46, 0x01, 0x2B, 0x2C, 0xD1, 0x01, 0x20, 0xB2, 0x4A, 0x10, 0xE0, 0x00, 0xBF, + 0x17, 0xF8, 0x10, 0x10, 0x11, 0xB1, 0x49, 0x1E, 0x07, 0xF8, 0x10, 0x10, 0x07, 0xEB, 0x40, 0x04, + 0x11, 0x78, 0x63, 0x78, 0x49, 0x1E, 0x8B, 0x42, 0x01, 0xDA, 0x5B, 0x1C, 0x63, 0x70, 0x40, 0x1C, + 0x39, 0x7E, 0x81, 0x42, 0xEC, 0xD2, 0x01, 0x20, 0xA7, 0x4B, 0x0F, 0xE0, 0x16, 0xF8, 0x10, 0x10, + 0x11, 0xB1, 0x49, 0x1E, 0x06, 0xF8, 0x10, 0x10, 0x06, 0xEB, 0x40, 0x02, 0x1C, 0x78, 0x51, 0x78, + 0x64, 0x1E, 0xA1, 0x42, 0x01, 0xDA, 0x49, 0x1C, 0x51, 0x70, 0x40, 0x1C, 0x31, 0x7E, 0x81, 0x42, + 0xEC, 0xD2, 0x9E, 0x48, 0x4F, 0xF0, 0x01, 0x09, 0xCB, 0x46, 0x00, 0x68, 0xB0, 0xF8, 0x8E, 0x02, + 0x40, 0x43, 0x03, 0x90, 0x00, 0x20, 0x01, 0x90, 0x62, 0xE0, 0x01, 0x20, 0x5A, 0xE0, 0x00, 0x20, + 0x00, 0x90, 0x9A, 0xF8, 0x38, 0x04, 0x06, 0xEB, 0x48, 0x03, 0x07, 0xEB, 0x49, 0x02, 0x19, 0xE0, + 0x00, 0xEB, 0xC0, 0x04, 0x0A, 0xEB, 0xC4, 0x01, 0x16, 0xF8, 0x18, 0x50, 0x11, 0xF8, 0x3E, 0x4F, + 0xAC, 0x42, 0x0F, 0xD3, 0x5D, 0x78, 0xAC, 0x42, 0x0C, 0xD8, 0x49, 0x78, 0x17, 0xF8, 0x19, 0x40, + 0xA1, 0x42, 0x07, 0xD3, 0x54, 0x78, 0xA1, 0x42, 0x04, 0xD8, 0x00, 0x9C, 0x0B, 0xFA, 0x00, 0xF1, + 0x21, 0x43, 0x00, 0x91, 0x40, 0x1E, 0xE3, 0xD2, 0x04, 0x21, 0x68, 0x46, 0x0B, 0xF0, 0x7A, 0xFE, + 0x01, 0x28, 0x2D, 0xDD, 0x00, 0x24, 0x58, 0x46, 0x00, 0x99, 0x01, 0xE0, 0x64, 0x1C, 0xE4, 0xB2, + 0x00, 0xFA, 0x04, 0xF2, 0x0A, 0x42, 0xF9, 0xD0, 0x04, 0xEB, 0xC4, 0x00, 0x0A, 0xEB, 0xC0, 0x00, + 0x9A, 0xF8, 0x38, 0x54, 0x0C, 0x30, 0x02, 0x90, 0x17, 0xE0, 0x00, 0xBF, 0x00, 0x99, 0x0B, 0xFA, + 0x05, 0xF0, 0x08, 0x42, 0x11, 0xD0, 0x05, 0xEB, 0xC5, 0x02, 0x0A, 0xEB, 0xC2, 0x01, 0x0C, 0x31, + 0x02, 0x98, 0x07, 0xF0, 0x3E, 0xFF, 0x03, 0x99, 0x88, 0x42, 0x06, 0xD2, 0xEA, 0xB2, 0x21, 0x46, + 0x50, 0x46, 0xFF, 0xF7, 0x0C, 0xFF, 0x01, 0x20, 0x01, 0x90, 0x6D, 0x1E, 0xA5, 0x42, 0xE5, 0xD8, + 0x08, 0xF1, 0x01, 0x00, 0x31, 0x7E, 0x80, 0x46, 0x41, 0x45, 0xA0, 0xD2, 0x09, 0xF1, 0x01, 0x09, + 0x39, 0x7E, 0x49, 0x45, 0x99, 0xD2, 0x01, 0x98, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x9F, 0x64, 0x48, + 0x10, 0xB5, 0x40, 0x78, 0x0C, 0x46, 0x00, 0x28, 0x52, 0xD0, 0x62, 0x48, 0x00, 0x78, 0x00, 0x28, + 0x4E, 0xD1, 0x61, 0x48, 0x00, 0x78, 0x00, 0x28, 0x4A, 0xD1, 0x5C, 0x48, 0x94, 0xF8, 0x38, 0x24, + 0x00, 0x68, 0x90, 0xF8, 0x89, 0x12, 0x8A, 0x42, 0x42, 0xD8, 0x00, 0x23, 0x09, 0xE0, 0x00, 0xBF, + 0x02, 0xEB, 0xC2, 0x01, 0x04, 0xEB, 0xC1, 0x01, 0xB1, 0xF9, 0x32, 0x10, 0x99, 0x42, 0x00, 0xDD, + 0x0B, 0x46, 0x52, 0x1E, 0xF4, 0xD2, 0x55, 0x49, 0x0B, 0x80, 0xB0, 0xF8, 0x8A, 0x12, 0x99, 0x42, + 0x2E, 0xDB, 0xB0, 0xF9, 0x8C, 0x12, 0x00, 0x22, 0x51, 0x48, 0xFB, 0xF7, 0x78, 0xFE, 0x50, 0x4A, + 0xD2, 0xE9, 0x00, 0x10, 0x01, 0x43, 0x23, 0xD0, 0xD2, 0xE9, 0x02, 0x01, 0x08, 0x43, 0x1F, 0xD0, + 0xA2, 0xF1, 0x40, 0x01, 0x01, 0x23, 0xA1, 0xF1, 0x40, 0x00, 0xFB, 0xF7, 0x41, 0xFB, 0x48, 0x48, + 0x80, 0x38, 0x00, 0x7E, 0x00, 0x28, 0x13, 0xD0, 0x45, 0x49, 0x40, 0x39, 0x09, 0x7E, 0x00, 0x29, + 0x0E, 0xD0, 0x48, 0x43, 0x94, 0xF8, 0x38, 0x14, 0x00, 0x23, 0x88, 0x42, 0x00, 0xD2, 0x01, 0x23, + 0x3F, 0x4A, 0x20, 0x46, 0x40, 0x3A, 0xBD, 0xE8, 0x10, 0x40, 0xA2, 0xF1, 0x40, 0x01, 0xFC, 0xE6, + 0x10, 0xBD, 0x3A, 0x49, 0x00, 0x20, 0xC8, 0x60, 0x39, 0x48, 0x0F, 0x21, 0x10, 0x30, 0x0D, 0xF0, + 0x3A, 0xB9, 0x90, 0xF8, 0x42, 0x00, 0x40, 0x07, 0x01, 0xD5, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, + 0x70, 0x47, 0x90, 0xF8, 0x3E, 0x01, 0x01, 0x28, 0x00, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x90, 0xF8, + 0x3E, 0x01, 0x02, 0x28, 0x05, 0xD0, 0x03, 0x28, 0x03, 0xD0, 0x04, 0x28, 0x01, 0xD0, 0x00, 0x20, + 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x90, 0xF8, 0x42, 0x10, 0x49, 0x06, 0x03, 0xD5, + 0xFF, 0xF7, 0xED, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x91, 0xF8, 0x3E, 0x21, + 0x01, 0x2A, 0x08, 0xD0, 0x02, 0x2A, 0x06, 0xD0, 0x06, 0x20, 0x81, 0xF8, 0x3E, 0x01, 0x00, 0x20, + 0x81, 0xF8, 0x43, 0x01, 0x70, 0x47, 0x00, 0xF0, 0xCD, 0xBD, 0xF0, 0xB5, 0x91, 0xF9, 0x49, 0x61, + 0x93, 0xF9, 0x00, 0x40, 0x92, 0xF9, 0x49, 0x51, 0x77, 0x1C, 0x02, 0xD0, 0x6D, 0x1C, 0x15, 0xD0, + 0x0B, 0xE0, 0x6E, 0x1C, 0x0B, 0xD0, 0x00, 0xEB, 0x85, 0x02, 0x00, 0xEB, 0x84, 0x00, 0xD2, 0x6B, + 0xC2, 0xF8, 0x4C, 0x11, 0xC1, 0x63, 0x81, 0xF8, 0x49, 0x41, 0x1C, 0x70, 0xF0, 0xBD, 0x64, 0x1C, + 0x64, 0xB2, 0x40, 0xF8, 0x24, 0x10, 0x81, 0xF8, 0x49, 0x41, 0x02, 0xE0, 0x00, 0xEB, 0x86, 0x01, + 0xC9, 0x6B, 0x00, 0xEB, 0x84, 0x00, 0xC1, 0xF8, 0x4C, 0x21, 0xC2, 0x63, 0x82, 0xF8, 0x49, 0x41, + 0xEB, 0xE7, 0x00, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xEC, 0x06, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xE0, 0x05, 0x10, 0x00, + 0x60, 0x25, 0x10, 0x00, 0xF0, 0xB5, 0x44, 0x88, 0x4E, 0x88, 0x01, 0x25, 0xA4, 0x1B, 0x24, 0xB2, + 0x00, 0x2C, 0x01, 0xDB, 0x26, 0x46, 0x00, 0xE0, 0x66, 0x42, 0x5E, 0x80, 0x56, 0x42, 0x94, 0x42, + 0x02, 0xDD, 0x44, 0x88, 0xA4, 0x1A, 0x03, 0xE0, 0xB4, 0x42, 0x03, 0xDA, 0x44, 0x88, 0x14, 0x44, + 0x4C, 0x80, 0x00, 0x25, 0x04, 0x88, 0x0F, 0x88, 0xE4, 0x1B, 0x24, 0xB2, 0x00, 0x2C, 0x01, 0xDB, + 0x27, 0x46, 0x00, 0xE0, 0x67, 0x42, 0x1F, 0x80, 0x94, 0x42, 0x02, 0xDD, 0x00, 0x88, 0x80, 0x1A, + 0x03, 0xE0, 0xB4, 0x42, 0x03, 0xDA, 0x00, 0x88, 0x10, 0x44, 0x08, 0x80, 0x00, 0x25, 0x28, 0x46, + 0xF0, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x96, 0x4D, 0x0F, 0x46, 0x06, 0x46, 0x81, 0x89, 0x28, 0x68, + 0x90, 0x46, 0xF9, 0xB1, 0x90, 0xF8, 0xCC, 0x43, 0x0D, 0xF0, 0x3E, 0xF9, 0x18, 0xB1, 0x28, 0x68, + 0x90, 0xF8, 0xCE, 0x43, 0x12, 0xE0, 0xB0, 0x7D, 0x02, 0x28, 0x04, 0xD0, 0x01, 0x28, 0x06, 0xD0, + 0x03, 0x28, 0x08, 0xD0, 0x0A, 0xE0, 0x28, 0x68, 0x90, 0xF8, 0xD3, 0x43, 0x06, 0xE0, 0x28, 0x68, + 0x90, 0xF8, 0x53, 0x44, 0x02, 0xE0, 0x28, 0x68, 0x90, 0xF8, 0x2C, 0x44, 0xB0, 0x89, 0x40, 0x1E, + 0xB0, 0x81, 0x11, 0xE0, 0xB1, 0x7D, 0x90, 0xF8, 0xD0, 0x43, 0x02, 0x29, 0x04, 0xD0, 0x01, 0x29, + 0x05, 0xD0, 0x03, 0x29, 0x06, 0xD0, 0x07, 0xE0, 0x90, 0xF8, 0xD3, 0x43, 0x04, 0xE0, 0x90, 0xF8, + 0x54, 0x44, 0x01, 0xE0, 0x90, 0xF8, 0x2D, 0x44, 0x29, 0x68, 0xB2, 0x7D, 0x91, 0xF8, 0xCF, 0x03, + 0x02, 0x2A, 0x04, 0xD0, 0x01, 0x2A, 0x05, 0xD0, 0x03, 0x2A, 0x06, 0xD0, 0x07, 0xE0, 0x91, 0xF8, + 0xD2, 0x03, 0x04, 0xE0, 0x91, 0xF8, 0x55, 0x04, 0x01, 0xE0, 0x91, 0xF8, 0x2E, 0x04, 0x38, 0x80, + 0xA8, 0xF8, 0x00, 0x40, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0xF1, 0x5E, 0x04, + 0x85, 0xB0, 0x4F, 0xF0, 0x00, 0x0B, 0x84, 0xF8, 0x15, 0xB0, 0xDF, 0xF8, 0xA4, 0x91, 0x0E, 0x46, + 0x80, 0xF8, 0x74, 0xB0, 0x05, 0x46, 0xB0, 0xF8, 0x42, 0x10, 0x4F, 0xF0, 0x01, 0x08, 0xD9, 0xF8, + 0x00, 0x00, 0x4A, 0x06, 0xC2, 0x46, 0x01, 0xD5, 0x02, 0x21, 0x0F, 0xE0, 0x0A, 0x07, 0x06, 0xD5, + 0x90, 0xF8, 0x40, 0x24, 0x52, 0x06, 0x02, 0xD5, 0x84, 0xF8, 0x16, 0xA0, 0x07, 0xE0, 0x90, 0xF8, + 0x20, 0x24, 0x92, 0x07, 0x03, 0xD5, 0x09, 0x06, 0x01, 0xD5, 0x03, 0x21, 0xA1, 0x75, 0x95, 0xF8, + 0x3E, 0x11, 0x03, 0x29, 0x09, 0xD0, 0xA2, 0x7C, 0x01, 0x2A, 0x06, 0xD0, 0x04, 0x29, 0x2D, 0xD0, + 0x07, 0x29, 0x2B, 0xD0, 0x08, 0x29, 0x76, 0xD0, 0x9C, 0xE0, 0x90, 0xF8, 0xCB, 0x73, 0x0D, 0xF0, + 0xBB, 0xF8, 0x18, 0xB1, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xCD, 0x73, 0x95, 0xF8, 0x3E, 0x01, + 0x03, 0x28, 0x00, 0xD0, 0x00, 0x27, 0xA0, 0x7D, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x28, 0x05, 0xD0, + 0x08, 0xE0, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x52, 0x74, 0x03, 0xE0, 0xD9, 0xF8, 0x00, 0x00, + 0x90, 0xF8, 0x2B, 0x74, 0xA7, 0x81, 0x31, 0x68, 0x21, 0x60, 0x31, 0x68, 0x61, 0x60, 0x84, 0xF8, + 0x14, 0xA0, 0x84, 0xF8, 0x13, 0xA0, 0x84, 0xF8, 0x12, 0xB0, 0x73, 0xE0, 0x02, 0xAA, 0x01, 0xA9, + 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFF, 0x03, 0xAB, 0xBD, 0xF9, 0x08, 0x20, 0x21, 0x46, 0x30, 0x46, + 0xFF, 0xF7, 0x10, 0xFF, 0x83, 0x46, 0x04, 0xAB, 0xBD, 0xF9, 0x04, 0x20, 0x21, 0x1D, 0x30, 0x46, + 0xFF, 0xF7, 0x08, 0xFF, 0x07, 0x46, 0xBB, 0xF1, 0x01, 0x0F, 0x03, 0xD0, 0x20, 0x7D, 0x01, 0x28, + 0x4D, 0xD0, 0x4E, 0xE0, 0xBD, 0xF9, 0x0C, 0x00, 0xBD, 0xF9, 0x0E, 0x10, 0x81, 0x42, 0x00, 0xDD, + 0x08, 0x46, 0xD9, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xD1, 0x23, 0x02, 0xF0, 0x0F, 0x03, 0x4F, 0xEA, + 0x12, 0x1C, 0xA2, 0x7D, 0x02, 0x2A, 0x04, 0xD0, 0x01, 0x2A, 0x05, 0xD0, 0x03, 0x2A, 0x06, 0xD0, + 0x0B, 0xE0, 0x91, 0xF8, 0xD4, 0x13, 0x04, 0xE0, 0x91, 0xF8, 0x56, 0x14, 0x01, 0xE0, 0x91, 0xF8, + 0x2F, 0x14, 0x01, 0xF0, 0x0F, 0x03, 0x4F, 0xEA, 0x11, 0x1C, 0x01, 0x2F, 0x0C, 0xD0, 0xCD, 0xF8, + 0x00, 0xC0, 0xBD, 0xF9, 0x08, 0x20, 0xBD, 0xF9, 0x04, 0x10, 0x07, 0xF0, 0x30, 0xFD, 0x21, 0x7D, + 0x01, 0x29, 0x0D, 0xD0, 0x18, 0xE0, 0x23, 0xE0, 0xA0, 0x68, 0x30, 0x60, 0xD9, 0xF8, 0x00, 0x00, + 0x90, 0xF8, 0x80, 0x03, 0x00, 0x06, 0x01, 0xD4, 0x4F, 0xF0, 0x00, 0x08, 0x60, 0x46, 0xEE, 0xE7, + 0x95, 0xF8, 0x41, 0x11, 0x41, 0xB9, 0xD9, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xBC, 0x13, 0x0A, 0x09, + 0xD4, 0xF8, 0x0E, 0x10, 0x07, 0xF0, 0x28, 0xFD, 0xC4, 0xF8, 0x0E, 0x00, 0x01, 0xE0, 0x84, 0xF8, + 0x15, 0xA0, 0x84, 0xF8, 0x14, 0xB0, 0xE7, 0x74, 0xB8, 0xF1, 0x00, 0x0F, 0x02, 0xD1, 0x03, 0xE0, + 0xA0, 0x68, 0x30, 0x60, 0x30, 0x68, 0xA0, 0x60, 0x05, 0xB0, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x8F, + 0x20, 0x07, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x17, 0x46, 0x06, 0x46, 0xDD, 0xE9, 0x06, 0xC2, + 0xC8, 0x78, 0x00, 0x25, 0x0C, 0x46, 0x03, 0x28, 0x30, 0xD2, 0xFE, 0x48, 0xDF, 0xF8, 0xF8, 0xE3, + 0x01, 0x68, 0x91, 0xF8, 0x0A, 0x14, 0xA1, 0x70, 0xDE, 0xF8, 0x04, 0xE0, 0xBE, 0xF1, 0x00, 0x0F, + 0x06, 0xDD, 0xD0, 0xF8, 0x00, 0xE0, 0x9E, 0xF8, 0x0B, 0xE4, 0xA1, 0xEB, 0x0E, 0x01, 0xA1, 0x70, + 0x00, 0x68, 0x71, 0x6B, 0xB0, 0xF8, 0x0C, 0x04, 0x81, 0x42, 0x15, 0xDD, 0xDB, 0xB2, 0x39, 0x46, + 0x60, 0x46, 0x00, 0xF0, 0xE8, 0xFA, 0xE0, 0x78, 0x40, 0x1C, 0xC0, 0xB2, 0xE0, 0x70, 0x03, 0x28, + 0x06, 0xD0, 0xEE, 0x49, 0xB6, 0xF9, 0x56, 0x00, 0xB1, 0xF9, 0x00, 0x10, 0x88, 0x42, 0x05, 0xDD, + 0x03, 0x20, 0xE0, 0x70, 0x01, 0x25, 0x01, 0xE0, 0x00, 0x20, 0xE0, 0x70, 0x28, 0x46, 0xBD, 0xE8, + 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x5F, 0x4F, 0xF0, 0x00, 0x0B, 0x0C, 0x46, 0x81, 0x46, 0x5D, 0x46, + 0x4F, 0xF0, 0x02, 0x0A, 0x01, 0x26, 0x00, 0xF5, 0x80, 0x57, 0x7C, 0xE0, 0xD7, 0xF8, 0xB0, 0x03, + 0x06, 0xFA, 0x05, 0xFE, 0x10, 0xEA, 0x0E, 0x0F, 0x74, 0xD0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, + 0x40, 0x01, 0x09, 0xEB, 0x01, 0x10, 0x00, 0xF5, 0x9A, 0x71, 0x90, 0xF8, 0x3E, 0x81, 0xB0, 0xF9, + 0x0C, 0xC0, 0xB8, 0xF1, 0x01, 0x0F, 0x0F, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0x0C, 0xD0, 0x90, 0xF8, + 0x42, 0x00, 0x40, 0x07, 0x51, 0xD5, 0xD2, 0x48, 0xEB, 0xB2, 0x61, 0x46, 0xB0, 0xF9, 0x08, 0x20, + 0x20, 0x46, 0x00, 0xF0, 0xA0, 0xFA, 0x55, 0xE0, 0xCE, 0x4B, 0xB0, 0xF9, 0x54, 0x20, 0xB3, 0xF9, + 0x00, 0x30, 0x9A, 0x42, 0x4E, 0xDB, 0xB8, 0xF1, 0x01, 0x0F, 0x03, 0xD1, 0x00, 0x22, 0x0A, 0x60, + 0x4A, 0x60, 0x0A, 0x81, 0xC6, 0x4A, 0xB2, 0xF9, 0x00, 0x30, 0x63, 0x45, 0x03, 0xDC, 0xB2, 0xF9, + 0x02, 0x30, 0x63, 0x45, 0x0C, 0xDA, 0xB0, 0xF8, 0x42, 0x30, 0x43, 0xF0, 0x04, 0x03, 0xA0, 0xF8, + 0x42, 0x30, 0xC3, 0x68, 0x4B, 0x60, 0x81, 0xF8, 0x08, 0xA0, 0xB2, 0xF9, 0x00, 0x20, 0x19, 0xE0, + 0xB2, 0xF9, 0x08, 0x30, 0x63, 0x45, 0x03, 0xDC, 0xB2, 0xF9, 0x0A, 0x30, 0x63, 0x45, 0x19, 0xDA, + 0xB0, 0xF8, 0x42, 0x30, 0x43, 0xF0, 0x04, 0x03, 0xA0, 0xF8, 0x42, 0x30, 0x90, 0xF8, 0x3E, 0x31, + 0x01, 0x2B, 0x02, 0xD0, 0x0B, 0x7A, 0x02, 0x2B, 0x01, 0xD1, 0xC3, 0x68, 0x4B, 0x60, 0x0E, 0x72, + 0xB2, 0xF9, 0x08, 0x20, 0x2B, 0x46, 0xCD, 0xE9, 0x00, 0x42, 0x62, 0x46, 0xFF, 0xF7, 0x4A, 0xFF, + 0x83, 0x46, 0x0F, 0xE0, 0x00, 0x20, 0x08, 0x72, 0x08, 0xE0, 0xA9, 0x48, 0xB0, 0xF9, 0x08, 0x10, + 0x61, 0x45, 0x07, 0xDA, 0xB0, 0xF9, 0x0A, 0x00, 0x60, 0x45, 0x03, 0xDD, 0xA0, 0x68, 0x40, 0xEA, + 0x0E, 0x00, 0xA0, 0x60, 0x6D, 0x1C, 0x97, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0xBF, 0xF6, 0x7E, 0xAF, + 0x20, 0x68, 0x61, 0x68, 0x9C, 0x4A, 0x50, 0xEA, 0x01, 0x03, 0xA3, 0x68, 0x01, 0xD0, 0x23, 0xB1, + 0x04, 0xE0, 0x1B, 0xB1, 0x82, 0xF8, 0x00, 0xA0, 0x00, 0xE0, 0x16, 0x70, 0x98, 0x4A, 0x18, 0x32, + 0x13, 0x68, 0x98, 0x43, 0x20, 0x60, 0x50, 0x68, 0x81, 0x43, 0x61, 0x60, 0x96, 0x49, 0xA0, 0x68, + 0x09, 0x78, 0x08, 0x43, 0x05, 0xD1, 0x92, 0x49, 0x18, 0x22, 0x18, 0x39, 0x90, 0x48, 0x0C, 0xF0, + 0x1E, 0xFE, 0x58, 0x46, 0xBD, 0xE8, 0xFC, 0x9F, 0x8B, 0x4A, 0x10, 0xB5, 0x12, 0x78, 0x00, 0x21, + 0x01, 0x2A, 0x01, 0xD1, 0x03, 0xB1, 0x01, 0x21, 0x90, 0xF8, 0x3E, 0x21, 0x04, 0x2A, 0x18, 0xD1, + 0x84, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x00, 0x34, 0x5B, 0x07, 0x12, 0xD5, 0xB0, 0xF8, 0x4A, 0x30, + 0xB0, 0xF8, 0x4C, 0x40, 0x1B, 0x1B, 0x82, 0x4C, 0xA4, 0x8A, 0xA3, 0x42, 0x09, 0xDD, 0x90, 0xF8, + 0x5B, 0x30, 0x90, 0xF8, 0x5A, 0x00, 0x92, 0xF8, 0x09, 0x24, 0x18, 0x1A, 0x90, 0x42, 0x00, 0xDD, + 0x01, 0x21, 0x08, 0x46, 0x10, 0xBD, 0x30, 0xB5, 0x79, 0x4D, 0x00, 0x24, 0x18, 0x35, 0x09, 0xB1, + 0x29, 0x68, 0x11, 0xB9, 0x12, 0xB1, 0x69, 0x68, 0x01, 0xB1, 0x01, 0x24, 0x72, 0x49, 0x09, 0x78, + 0x01, 0x29, 0x01, 0xD1, 0x03, 0xB1, 0x01, 0x24, 0x6E, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x00, 0x24, + 0x52, 0x07, 0x16, 0xD5, 0x90, 0xF8, 0x3E, 0x21, 0x04, 0x2A, 0x12, 0xD1, 0xB0, 0xF8, 0x4A, 0x20, + 0xB0, 0xF8, 0x4C, 0x30, 0xD2, 0x1A, 0x6A, 0x4B, 0x9B, 0x8A, 0x9A, 0x42, 0x09, 0xDD, 0x90, 0xF8, + 0x5B, 0x20, 0x90, 0xF8, 0x5A, 0x00, 0x91, 0xF8, 0x09, 0x14, 0x10, 0x1A, 0x88, 0x42, 0x00, 0xDD, + 0x01, 0x24, 0x20, 0x46, 0x30, 0xBD, 0x2D, 0xE9, 0xF3, 0x4F, 0x8D, 0xB0, 0x5E, 0x48, 0x00, 0x25, + 0x8B, 0x46, 0x0A, 0x95, 0x01, 0x78, 0x5E, 0x48, 0x18, 0x38, 0x01, 0x29, 0x06, 0xD1, 0xDB, 0xF8, + 0x08, 0x10, 0x19, 0xB1, 0xD0, 0xF8, 0x1C, 0x80, 0x47, 0x6A, 0x02, 0xE0, 0xD0, 0xF8, 0x18, 0x80, + 0x07, 0x6A, 0x0D, 0x9E, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x09, 0x06, 0xF5, 0x80, 0x56, 0x0F, 0xE1, + 0x09, 0xFA, 0x04, 0xF0, 0xD6, 0xF8, 0xB0, 0x13, 0x0B, 0x90, 0x01, 0x42, 0x1A, 0xD0, 0xC4, 0xEB, + 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x0D, 0x98, 0x00, 0xEB, 0x01, 0x1A, 0x9A, 0xF8, 0x42, 0x00, + 0x40, 0x07, 0x0F, 0xD5, 0x0A, 0xF5, 0x9A, 0x70, 0x01, 0x90, 0xBA, 0xF9, 0x0C, 0x00, 0x02, 0x90, + 0x9A, 0xF8, 0x3E, 0x01, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x1F, 0xD0, + 0x05, 0x28, 0x7D, 0xD0, 0xEB, 0xE0, 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x04, 0x20, 0xDB, 0xF8, + 0x08, 0x30, 0x50, 0x46, 0xFF, 0xF7, 0x60, 0xFF, 0x01, 0x28, 0x02, 0xD1, 0x01, 0x99, 0x81, 0xF8, + 0x01, 0x90, 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x04, 0x20, 0xDB, 0xF8, 0x08, 0x30, 0x50, 0x46, + 0xFF, 0xF7, 0x79, 0xFF, 0x01, 0x28, 0xE5, 0xD1, 0x01, 0x99, 0x00, 0x20, 0x88, 0x70, 0xCE, 0xE0, + 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x04, 0x20, 0xDB, 0xF8, 0x08, 0x30, 0x50, 0x46, 0xFF, 0xF7, + 0x6A, 0xFF, 0x01, 0x28, 0x09, 0xD0, 0x01, 0x98, 0x80, 0x78, 0x48, 0xB1, 0x01, 0x99, 0x40, 0x1E, + 0x10, 0xF0, 0xFF, 0x00, 0x88, 0x70, 0x03, 0xD0, 0x07, 0xE0, 0x01, 0x99, 0x00, 0x20, 0x88, 0x70, + 0x9A, 0xF8, 0x46, 0x11, 0x09, 0xFA, 0x01, 0xF0, 0x05, 0x43, 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, + 0x04, 0x20, 0xDB, 0xF8, 0x08, 0x30, 0x50, 0x46, 0xFF, 0xF7, 0x26, 0xFF, 0x01, 0x28, 0x02, 0xD1, + 0x01, 0x99, 0x81, 0xF8, 0x01, 0x90, 0x01, 0x98, 0xC0, 0x78, 0x03, 0x28, 0x1D, 0xD2, 0x01, 0x99, + 0x89, 0x78, 0xD1, 0xB1, 0x17, 0x49, 0xDA, 0xF8, 0x34, 0x20, 0x09, 0x68, 0xB1, 0xF8, 0x0C, 0x14, + 0x8A, 0x42, 0x0F, 0xDD, 0x40, 0x1C, 0x01, 0x99, 0xC0, 0xB2, 0x03, 0x28, 0xC8, 0x70, 0x06, 0xD0, + 0x12, 0x49, 0xBA, 0xF9, 0x56, 0x00, 0xB1, 0xF9, 0x00, 0x10, 0x88, 0x42, 0x05, 0xDD, 0x01, 0x20, + 0x0A, 0x90, 0x02, 0xE0, 0x01, 0x99, 0x00, 0x20, 0xC8, 0x70, 0x02, 0x98, 0x0F, 0xFA, 0x88, 0xF2, + 0x82, 0x42, 0x04, 0xDC, 0x02, 0x98, 0x4F, 0xEA, 0x28, 0x41, 0x81, 0x42, 0x16, 0xDA, 0x01, 0x98, + 0x02, 0x21, 0xE3, 0xB2, 0x01, 0x72, 0x01, 0x98, 0xDA, 0xF8, 0x0C, 0x10, 0x41, 0x60, 0x37, 0xE0, + 0x56, 0xE0, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0xF0, 0x05, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00, + 0x98, 0x25, 0x10, 0x00, 0x7C, 0x06, 0x10, 0x00, 0xF3, 0x06, 0x10, 0x00, 0x38, 0xB2, 0x02, 0x99, + 0x04, 0x90, 0x88, 0x42, 0x03, 0xDC, 0x02, 0x98, 0x39, 0x14, 0x81, 0x42, 0x25, 0xDA, 0x01, 0x98, + 0x00, 0x7A, 0x02, 0x28, 0x06, 0xD1, 0x01, 0x99, 0x81, 0xF8, 0x08, 0x90, 0x01, 0x98, 0xDA, 0xF8, + 0x0C, 0x10, 0x41, 0x60, 0x01, 0x98, 0x40, 0x78, 0x80, 0xB9, 0x01, 0x98, 0x53, 0x46, 0x80, 0x78, + 0x00, 0x28, 0x82, 0x48, 0x02, 0x69, 0x04, 0xD0, 0x01, 0x98, 0x0A, 0xF1, 0x0C, 0x01, 0x00, 0x1D, + 0x02, 0xE0, 0x0A, 0xF1, 0x10, 0x01, 0x08, 0x1F, 0x00, 0xF0, 0xE2, 0xF8, 0x04, 0x9A, 0xE3, 0xB2, + 0x58, 0x46, 0x02, 0x99, 0x00, 0xF0, 0xCF, 0xF8, 0x31, 0xE0, 0xDB, 0xF8, 0x08, 0x00, 0x0B, 0x99, + 0x08, 0x43, 0xCB, 0xF8, 0x08, 0x00, 0x01, 0x98, 0x80, 0x78, 0x20, 0xB1, 0x01, 0x99, 0x00, 0x22, + 0x50, 0x46, 0x09, 0x1D, 0x03, 0xE0, 0x01, 0x22, 0x0A, 0xF1, 0x0C, 0x01, 0x50, 0x46, 0x00, 0xF0, + 0xA8, 0xF8, 0xBA, 0xF8, 0x42, 0x00, 0x20, 0xF0, 0x04, 0x01, 0xAA, 0xF8, 0x42, 0x10, 0x16, 0xE0, + 0x01, 0x98, 0x00, 0x7A, 0x01, 0x28, 0x12, 0xD1, 0x01, 0x98, 0x80, 0x78, 0x78, 0xB1, 0x01, 0x99, + 0x01, 0x22, 0x50, 0x46, 0x09, 0x1D, 0x00, 0xF0, 0x94, 0xF8, 0xBA, 0xF8, 0x42, 0x00, 0x20, 0xF0, + 0x04, 0x01, 0xAA, 0xF8, 0x42, 0x10, 0xBA, 0xF8, 0x56, 0x10, 0xAA, 0xF8, 0x54, 0x10, 0x64, 0x1C, + 0x96, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0xBF, 0xF6, 0xEB, 0xAE, 0x5D, 0x48, 0x00, 0x68, 0x90, 0xF8, + 0x00, 0x04, 0x80, 0x07, 0x02, 0xD5, 0x28, 0x46, 0xFB, 0xF7, 0xA7, 0xFF, 0x59, 0x48, 0x15, 0xB1, + 0x80, 0xF8, 0x00, 0x90, 0x01, 0xE0, 0x00, 0x21, 0x01, 0x70, 0x0A, 0x98, 0x0F, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0x53, 0x49, 0x0B, 0x68, 0x51, 0x49, 0x9A, 0x8E, 0x18, 0x39, 0x12, 0x1A, 0x08, 0x80, + 0x4A, 0x80, 0x93, 0xF8, 0x0F, 0x34, 0x18, 0x44, 0x88, 0x80, 0xD0, 0x1A, 0xC8, 0x80, 0x70, 0x47, + 0x4B, 0x49, 0x0B, 0x68, 0x49, 0x49, 0x9A, 0x8E, 0x18, 0x39, 0x12, 0x1A, 0x08, 0x81, 0x4A, 0x81, + 0x93, 0xF8, 0x12, 0x34, 0x18, 0x44, 0x88, 0x81, 0xD0, 0x1A, 0xC8, 0x81, 0x70, 0x47, 0x10, 0xB5, + 0x43, 0x4C, 0x20, 0x68, 0x90, 0xF8, 0x0E, 0x04, 0xFF, 0xF7, 0xDB, 0xFF, 0x20, 0x68, 0x90, 0xF8, + 0x0E, 0x04, 0xFF, 0xF7, 0xE5, 0xFF, 0x22, 0x68, 0x3C, 0x49, 0x92, 0xF8, 0x10, 0x04, 0x18, 0x39, + 0x40, 0x43, 0x08, 0x61, 0x92, 0xF8, 0x11, 0x04, 0x88, 0x82, 0x18, 0x22, 0x37, 0x48, 0x0C, 0xF0, + 0x46, 0xFC, 0x38, 0x49, 0x00, 0x20, 0x35, 0x4A, 0x08, 0x70, 0x37, 0x49, 0x18, 0x3A, 0x48, 0x60, + 0x10, 0x63, 0x50, 0x63, 0x90, 0x63, 0x35, 0x4A, 0x10, 0x70, 0x08, 0x70, 0x10, 0xBD, 0xFE, 0xB5, + 0x00, 0x24, 0x06, 0x46, 0x00, 0x94, 0x01, 0x94, 0x69, 0x46, 0x02, 0x94, 0xFF, 0xF7, 0x61, 0xFD, + 0x05, 0x46, 0x69, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x66, 0xFE, 0x40, 0xEA, 0x05, 0x01, 0x2A, 0x48, + 0x01, 0x29, 0x01, 0xD0, 0x41, 0x68, 0x05, 0xE0, 0x25, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x0A, 0x14, + 0x49, 0x1F, 0x41, 0x60, 0x00, 0x29, 0x04, 0xDD, 0x49, 0x1E, 0x41, 0x60, 0x21, 0x49, 0x09, 0x78, + 0x01, 0xB9, 0x44, 0x60, 0x1D, 0x48, 0x9D, 0xE8, 0x0E, 0x00, 0x18, 0x30, 0x80, 0xE8, 0x0E, 0x00, + 0xFE, 0xBD, 0x02, 0x23, 0x80, 0xF8, 0x3E, 0x31, 0x00, 0x23, 0x80, 0xF8, 0x42, 0x31, 0x01, 0x2A, + 0x05, 0xD0, 0x09, 0x68, 0x01, 0x62, 0x01, 0x21, 0x80, 0xF8, 0x34, 0x11, 0x70, 0x47, 0x03, 0x22, + 0x0C, 0x30, 0x07, 0xF0, 0xBB, 0xB9, 0x10, 0xB5, 0x01, 0x24, 0x9C, 0x40, 0x91, 0x42, 0x03, 0xDA, + 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0x10, 0xBD, 0x41, 0x68, 0x21, 0x43, 0x41, 0x60, 0x10, 0xBD, + 0x70, 0xB5, 0x15, 0x46, 0x0A, 0x46, 0x06, 0x46, 0x01, 0x46, 0x1C, 0x46, 0x10, 0x46, 0x07, 0xF0, + 0xC8, 0xF9, 0xA8, 0x42, 0x09, 0xDD, 0x00, 0x22, 0x31, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xD1, 0xFF, + 0x34, 0xF8, 0x42, 0x0F, 0x20, 0xF0, 0x04, 0x00, 0x20, 0x80, 0x70, 0xBD, 0x98, 0x25, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, 0xF0, 0x05, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, + 0x10, 0xB5, 0x41, 0xF2, 0xA8, 0x41, 0x9F, 0x48, 0x0C, 0xF0, 0x25, 0xFC, 0x40, 0xF2, 0x3C, 0x41, + 0x9D, 0x48, 0x0C, 0xF0, 0x20, 0xFC, 0x9D, 0x48, 0xFF, 0x21, 0x80, 0xF8, 0xB8, 0x13, 0x00, 0xF0, + 0xFC, 0xFB, 0xFF, 0xF7, 0xD6, 0xFA, 0xFF, 0xF7, 0x5A, 0xFF, 0x00, 0xF0, 0x37, 0xF9, 0xFD, 0xF7, + 0x2B, 0xFA, 0xFD, 0xF7, 0x02, 0xFF, 0xFE, 0xF7, 0x87, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, + 0x37, 0xBF, 0x70, 0xB5, 0x92, 0x4D, 0x00, 0x24, 0x8E, 0x48, 0xAC, 0x71, 0x00, 0xF0, 0xEB, 0xFB, + 0x90, 0x4E, 0x30, 0x68, 0x90, 0xF8, 0x40, 0x04, 0xC0, 0x06, 0x05, 0xD5, 0x8E, 0x48, 0x00, 0x79, + 0x10, 0xB1, 0x88, 0x48, 0xFF, 0xF7, 0x5F, 0xF8, 0x30, 0x68, 0x90, 0xF8, 0x00, 0x04, 0xC0, 0x07, + 0x05, 0xD0, 0x84, 0x48, 0xFF, 0xF7, 0x5B, 0xFF, 0x82, 0x48, 0x00, 0xF0, 0x10, 0xF9, 0x81, 0x48, + 0xFD, 0xF7, 0x0A, 0xFA, 0x7F, 0x48, 0xFD, 0xF7, 0xE6, 0xFE, 0x7F, 0x48, 0x80, 0xF8, 0x38, 0x44, + 0x7E, 0x48, 0xB0, 0xF8, 0xBC, 0x03, 0xA5, 0xF8, 0x1F, 0x00, 0x70, 0xBD, 0x70, 0xB5, 0x7A, 0x4D, + 0x7B, 0x4E, 0x95, 0xF8, 0x38, 0x04, 0xD8, 0xB3, 0x7A, 0x4C, 0xB0, 0x71, 0x20, 0x68, 0x90, 0xF8, + 0x80, 0x02, 0x80, 0x07, 0x03, 0xD5, 0x29, 0x46, 0x72, 0x48, 0xFF, 0xF7, 0x30, 0xFA, 0x72, 0x49, + 0x70, 0x48, 0x00, 0xF0, 0xE3, 0xFB, 0x20, 0x68, 0x90, 0xF8, 0x40, 0x04, 0xC0, 0x06, 0x05, 0xD5, + 0x71, 0x48, 0x00, 0x79, 0x10, 0xB1, 0x6B, 0x48, 0xFF, 0xF7, 0x25, 0xF8, 0x20, 0x68, 0x90, 0xF8, + 0x00, 0x04, 0xC0, 0x07, 0x02, 0xD0, 0x67, 0x48, 0xFF, 0xF7, 0x21, 0xFF, 0x20, 0x68, 0x90, 0xF8, + 0x80, 0x03, 0xC0, 0x07, 0x02, 0xD0, 0x63, 0x48, 0xFE, 0xF7, 0xAC, 0xFF, 0x61, 0x48, 0x00, 0xF0, + 0xCE, 0xF8, 0x60, 0x48, 0xFD, 0xF7, 0xC8, 0xF9, 0x5E, 0x48, 0xFD, 0xF7, 0xA4, 0xFE, 0x00, 0x20, + 0x85, 0xF8, 0x38, 0x04, 0x5D, 0x48, 0xB0, 0xF8, 0xBC, 0x03, 0xA6, 0xF8, 0x1F, 0x00, 0x70, 0xBD, + 0xFF, 0xE7, 0xFF, 0xF7, 0x8E, 0xFF, 0xF5, 0xE7, 0x10, 0xB5, 0x59, 0x48, 0x00, 0x24, 0x84, 0x71, + 0x54, 0x48, 0x00, 0xF0, 0x78, 0xFB, 0x53, 0x48, 0xFD, 0xF7, 0xAE, 0xF9, 0x51, 0x48, 0xFC, 0xF7, + 0xCA, 0xFE, 0x51, 0x48, 0x80, 0xF8, 0x38, 0x44, 0x10, 0xBD, 0x10, 0xB5, 0x4E, 0x4C, 0x94, 0xF8, + 0x38, 0x04, 0x90, 0xB1, 0x4E, 0x49, 0x88, 0x71, 0x21, 0x46, 0x4A, 0x48, 0x00, 0xF0, 0x96, 0xFB, + 0x48, 0x48, 0x00, 0xF0, 0x9C, 0xF8, 0x47, 0x48, 0xFD, 0xF7, 0x96, 0xF9, 0x45, 0x48, 0xFC, 0xF7, + 0xB2, 0xFE, 0x00, 0x20, 0x84, 0xF8, 0x38, 0x04, 0x10, 0xBD, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xE7, + 0x10, 0xB5, 0x41, 0x4C, 0x01, 0x46, 0x94, 0xF8, 0x38, 0x04, 0x0F, 0x28, 0x0B, 0xD2, 0x00, 0xEB, + 0xC0, 0x00, 0x04, 0xEB, 0xC0, 0x00, 0x48, 0x22, 0x0C, 0xF0, 0x01, 0xFB, 0x94, 0xF8, 0x38, 0x04, + 0x40, 0x1C, 0x84, 0xF8, 0x38, 0x04, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x00, 0x21, + 0xD0, 0xF8, 0xB0, 0x33, 0x01, 0x22, 0x00, 0xBF, 0x02, 0xFA, 0x01, 0xF4, 0x23, 0x42, 0x0B, 0xD1, + 0x8A, 0x40, 0x13, 0x43, 0xC0, 0xF8, 0xB0, 0x33, 0x90, 0xF9, 0xB8, 0x23, 0x8A, 0x42, 0x01, 0xDA, + 0x80, 0xF8, 0xB8, 0x13, 0x48, 0xB2, 0x10, 0xBD, 0x49, 0x1C, 0x0F, 0x29, 0xEC, 0xDB, 0x4F, 0xF0, + 0xFF, 0x30, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x91, 0xF8, 0x4A, 0x41, 0x01, 0x23, + 0xD0, 0xF8, 0xB0, 0x23, 0xA3, 0x40, 0x9A, 0x43, 0xC0, 0xF8, 0xB0, 0x23, 0x00, 0x22, 0x81, 0xF8, + 0x3E, 0x21, 0x90, 0xF9, 0xB8, 0x23, 0x91, 0xF9, 0x4A, 0x11, 0x8A, 0x42, 0x07, 0xD1, 0xD0, 0xF8, + 0xB0, 0x13, 0xB1, 0xFA, 0x81, 0xF1, 0xC1, 0xF1, 0x1F, 0x01, 0x80, 0xF8, 0xB8, 0x13, 0x10, 0xBD, + 0x30, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x00, 0x22, 0xD0, 0xF8, 0xB4, 0x43, 0x01, 0x23, 0x00, 0xBF, + 0x03, 0xFA, 0x02, 0xF5, 0x2C, 0x42, 0x06, 0xD1, 0x93, 0x40, 0x1C, 0x43, 0xC0, 0xF8, 0xB4, 0x43, + 0x81, 0xF8, 0x4B, 0x21, 0x30, 0xBD, 0x52, 0x1C, 0x52, 0xB2, 0x0A, 0x2A, 0xF0, 0xDB, 0xFF, 0x20, + 0x81, 0xF8, 0x4B, 0x01, 0x30, 0xBD, 0x10, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x91, 0xF8, 0x4B, 0x41, + 0x01, 0x23, 0xD0, 0xF8, 0xB4, 0x23, 0xA3, 0x40, 0x9A, 0x43, 0xC0, 0xF8, 0xB4, 0x23, 0xFF, 0x20, + 0x81, 0xF8, 0x4B, 0x01, 0x10, 0xBD, 0x04, 0x48, 0x70, 0x47, 0x03, 0x48, 0x90, 0xF8, 0x38, 0x04, + 0x70, 0x47, 0x00, 0x00, 0xBC, 0x25, 0x10, 0x00, 0x64, 0x3A, 0x10, 0x00, 0xBC, 0x35, 0x10, 0x00, + 0xE6, 0x43, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x70, 0x47, 0x2D, 0xE9, + 0xF0, 0x47, 0x00, 0x24, 0x06, 0x46, 0x01, 0x27, 0xDF, 0xF8, 0xE0, 0x80, 0x4F, 0xF0, 0x05, 0x09, + 0x00, 0xF5, 0x80, 0x55, 0x64, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x04, 0xF1, + 0x08, 0x42, 0x5B, 0xD0, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x11, + 0x91, 0xF8, 0x3E, 0x01, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x02, 0xD0, 0x04, 0x28, 0x27, 0xD0, + 0x4C, 0xE0, 0x91, 0xF8, 0x3F, 0x01, 0x03, 0x28, 0x01, 0xD0, 0x04, 0x28, 0x46, 0xD1, 0x28, 0x48, + 0xB1, 0xF8, 0x42, 0x20, 0xB0, 0xF9, 0x00, 0x00, 0x53, 0x07, 0x02, 0xD5, 0x25, 0x48, 0xB0, 0xF9, + 0x00, 0x00, 0x13, 0x07, 0x02, 0xD5, 0x24, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0xB1, 0xF9, 0x54, 0x30, + 0x83, 0x42, 0x33, 0xDA, 0xD0, 0x05, 0x07, 0xD5, 0x20, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0x83, 0x42, + 0x02, 0xDD, 0x81, 0xF8, 0x3F, 0x71, 0x29, 0xE0, 0x30, 0x46, 0xFF, 0xF7, 0x5B, 0xFF, 0x25, 0xE0, + 0x91, 0xF8, 0x40, 0x00, 0x10, 0xF0, 0x06, 0x0F, 0x20, 0xD0, 0x91, 0xF8, 0x42, 0x00, 0x40, 0x07, + 0x1C, 0xD4, 0x17, 0x48, 0xB0, 0xF9, 0x00, 0x20, 0x16, 0x48, 0x00, 0x78, 0x01, 0x28, 0x01, 0xD1, + 0xB8, 0xF9, 0x00, 0x20, 0x91, 0xF8, 0x3F, 0x01, 0x03, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x07, 0xD0, + 0x0C, 0xE0, 0xB1, 0xF9, 0x54, 0x20, 0xB8, 0xF9, 0x00, 0x00, 0x82, 0x42, 0x04, 0xDB, 0x05, 0xE0, + 0xB1, 0xF9, 0x54, 0x00, 0x90, 0x42, 0x01, 0xDA, 0x81, 0xF8, 0x3E, 0x91, 0x64, 0x1C, 0x64, 0xB2, + 0x95, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0x97, 0xDA, 0xBD, 0xE8, 0xF0, 0x87, 0x6E, 0x06, 0x10, 0x00, + 0x68, 0x06, 0x10, 0x00, 0x7C, 0x06, 0x10, 0x00, 0x86, 0x06, 0x10, 0x00, 0x6C, 0x06, 0x10, 0x00, + 0x70, 0x06, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, 0x90, 0xF8, 0x40, 0x10, 0x09, 0x06, 0x14, 0xD5, + 0xB0, 0xF8, 0x42, 0x10, 0x0A, 0x07, 0x0C, 0xD4, 0xF8, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x40, 0x34, + 0x5B, 0x06, 0x06, 0xD5, 0x92, 0xF8, 0x80, 0x23, 0x52, 0x06, 0x02, 0xD4, 0x01, 0x22, 0x80, 0xF8, + 0x70, 0x20, 0x41, 0xF0, 0x08, 0x01, 0xA0, 0xF8, 0x42, 0x10, 0x70, 0x47, 0xB0, 0xF8, 0x40, 0x10, + 0xC9, 0x05, 0x14, 0xD5, 0xB0, 0xF8, 0x42, 0x10, 0x0A, 0x06, 0x0C, 0xD4, 0xEB, 0x4A, 0x12, 0x68, + 0x92, 0xF8, 0x20, 0x34, 0x9B, 0x07, 0x06, 0xD5, 0x92, 0xF8, 0x80, 0x23, 0x52, 0x06, 0x02, 0xD4, + 0x01, 0x22, 0x80, 0xF8, 0x70, 0x20, 0x41, 0xF0, 0x80, 0x01, 0xA0, 0xF8, 0x42, 0x10, 0x70, 0x47, + 0x2D, 0xE9, 0xF0, 0x47, 0x15, 0x46, 0x0C, 0x46, 0x82, 0x46, 0x01, 0xF1, 0x0C, 0x07, 0x4F, 0xF0, + 0x00, 0x08, 0x4F, 0xF0, 0xFF, 0x39, 0x02, 0xF1, 0x0C, 0x06, 0x53, 0xB3, 0x01, 0x20, 0x84, 0xF8, + 0x3E, 0x01, 0x95, 0xF8, 0x40, 0x00, 0x84, 0xF8, 0x3F, 0x01, 0x84, 0xF8, 0x4B, 0x91, 0x84, 0xF8, + 0x42, 0x81, 0x84, 0xF8, 0x43, 0x81, 0xA4, 0xF8, 0x42, 0x80, 0xC4, 0xF8, 0x2C, 0x80, 0x84, 0xF8, + 0x41, 0x81, 0x95, 0xF8, 0x42, 0x00, 0x84, 0xF8, 0x45, 0x01, 0x68, 0x8E, 0xA4, 0xF8, 0x56, 0x00, + 0x95, 0xF8, 0x41, 0x00, 0x84, 0xF8, 0x46, 0x01, 0xE8, 0x68, 0x20, 0x62, 0x03, 0x22, 0x31, 0x46, + 0x20, 0x46, 0x06, 0xF0, 0x53, 0xFF, 0x03, 0x22, 0x31, 0x46, 0x38, 0x46, 0x06, 0xF0, 0x4E, 0xFF, + 0x10, 0xE0, 0xE0, 0x6A, 0x03, 0x22, 0x40, 0x1C, 0xE0, 0x62, 0x31, 0x46, 0x20, 0x46, 0x06, 0xF0, + 0x39, 0xFF, 0x03, 0x22, 0x31, 0x46, 0x38, 0x46, 0x06, 0xF0, 0x34, 0xFF, 0x94, 0xF8, 0x44, 0x01, + 0x84, 0xF8, 0x45, 0x01, 0x95, 0xF8, 0x40, 0x00, 0x84, 0xF8, 0x3F, 0x01, 0x95, 0xF8, 0x42, 0x00, + 0x84, 0xF8, 0x44, 0x01, 0xE8, 0x8C, 0xA4, 0xF8, 0x44, 0x00, 0x28, 0x8D, 0xA4, 0xF8, 0x46, 0x00, + 0x68, 0x8D, 0xA4, 0xF8, 0x48, 0x00, 0xE8, 0x8D, 0xA4, 0xF8, 0x4A, 0x00, 0x28, 0x8E, 0xA4, 0xF8, + 0x4C, 0x00, 0x28, 0x8B, 0xA4, 0xF8, 0x4E, 0x00, 0xB5, 0xF9, 0x32, 0x00, 0xA4, 0xF8, 0x54, 0x00, + 0xA9, 0x69, 0x61, 0x63, 0xE9, 0x69, 0xA1, 0x63, 0x29, 0x6A, 0xE1, 0x63, 0xA9, 0x8E, 0xA4, 0xF8, + 0x58, 0x10, 0xA9, 0x8C, 0xA4, 0xF8, 0x40, 0x10, 0xD5, 0xF8, 0x36, 0x10, 0xC4, 0xF8, 0x5A, 0x10, + 0x69, 0x69, 0xE1, 0x61, 0x95, 0xF8, 0x43, 0x10, 0x84, 0xF8, 0x47, 0x11, 0x95, 0xF8, 0x44, 0x10, + 0x84, 0xF8, 0x48, 0x11, 0xB4, 0xF9, 0x56, 0x10, 0x81, 0x42, 0x01, 0xDA, 0xA4, 0xF8, 0x56, 0x00, + 0xC4, 0xF8, 0x4C, 0x81, 0x84, 0xF8, 0x49, 0x91, 0xA8, 0x8C, 0x80, 0x05, 0xB4, 0xF8, 0x42, 0x00, + 0x02, 0xD5, 0x40, 0xF4, 0x80, 0x70, 0x01, 0xE0, 0x20, 0xF4, 0x80, 0x70, 0xA4, 0xF8, 0x42, 0x00, + 0x21, 0x46, 0x50, 0x46, 0x00, 0xF0, 0x21, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0x2D, 0xFF, 0x20, 0x46, + 0xBD, 0xE8, 0xF0, 0x47, 0x42, 0xE7, 0xF0, 0xB5, 0xB1, 0xF9, 0x02, 0x60, 0xB2, 0xF9, 0x02, 0x50, + 0x78, 0x24, 0x06, 0xFB, 0x05, 0xF7, 0x00, 0x2F, 0x2A, 0xDD, 0xB1, 0xF9, 0x00, 0x70, 0xB2, 0xF9, + 0x00, 0xC0, 0x07, 0xFB, 0x0C, 0xF7, 0x00, 0x2F, 0x22, 0xDD, 0x76, 0x43, 0x5D, 0x43, 0x96, 0xFB, + 0xF5, 0xF5, 0x2D, 0xB2, 0x45, 0x80, 0xB1, 0xF9, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x20, 0x49, 0x43, + 0x5A, 0x43, 0x91, 0xFB, 0xF2, 0xF1, 0x0A, 0xB2, 0x02, 0x80, 0x78, 0x2D, 0x00, 0xDD, 0x44, 0x80, + 0xB0, 0xF9, 0x02, 0x30, 0x6F, 0xF0, 0x77, 0x01, 0x8B, 0x42, 0x00, 0xDA, 0x41, 0x80, 0x78, 0x2A, + 0x00, 0xDD, 0x04, 0x80, 0xB0, 0xF9, 0x00, 0x20, 0x8A, 0x42, 0x00, 0xDA, 0x01, 0x80, 0xF0, 0xBD, + 0x00, 0x21, 0x41, 0x80, 0xFA, 0xE7, 0x2D, 0xE9, 0xFF, 0x4F, 0xDF, 0xF8, 0xD4, 0x91, 0x83, 0x46, + 0x0F, 0x46, 0xD9, 0xF8, 0x04, 0x00, 0x71, 0x4D, 0x8F, 0xB0, 0x00, 0x21, 0x01, 0x60, 0x28, 0x68, + 0xB0, 0xF8, 0x82, 0x43, 0x0C, 0xF0, 0xF2, 0xF9, 0x01, 0x28, 0x04, 0xD1, 0x28, 0x68, 0xB0, 0xF8, + 0x84, 0x03, 0x00, 0xB1, 0x04, 0x46, 0x0C, 0xF0, 0xDF, 0xF9, 0x80, 0xB1, 0x28, 0x68, 0x69, 0x49, + 0xB0, 0xF8, 0x86, 0x43, 0xB0, 0xF8, 0x8A, 0x03, 0x09, 0x68, 0x88, 0x42, 0x07, 0xDA, 0x0C, 0xF0, + 0xDD, 0xF9, 0x01, 0x28, 0x03, 0xD1, 0x28, 0x68, 0xB0, 0xF8, 0x88, 0x03, 0x04, 0x44, 0x64, 0x43, + 0x02, 0x94, 0x28, 0x68, 0x00, 0x25, 0x0B, 0xF5, 0x80, 0x56, 0x90, 0xF8, 0x8C, 0x03, 0x4F, 0xF0, + 0x01, 0x0A, 0x05, 0x90, 0x65, 0xE0, 0x00, 0xBF, 0xD6, 0xF8, 0xB0, 0x13, 0x0A, 0xFA, 0x05, 0xF0, + 0x01, 0x42, 0x5C, 0xD0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x0B, 0xEB, 0x01, 0x14, + 0x94, 0xF8, 0x3E, 0x01, 0x07, 0x28, 0x52, 0xD0, 0x21, 0x46, 0x20, 0x1D, 0x06, 0xF0, 0x81, 0xFE, + 0x05, 0x99, 0x48, 0x43, 0x00, 0xFB, 0x01, 0xF8, 0x02, 0x99, 0x88, 0x45, 0x00, 0xDA, 0x88, 0x46, + 0x22, 0x46, 0x21, 0x1D, 0x08, 0xA8, 0x06, 0xF0, 0x6A, 0xFE, 0x22, 0x1D, 0x11, 0x1D, 0x0A, 0xA8, + 0x06, 0xF0, 0x65, 0xFE, 0xBD, 0xF9, 0x20, 0x00, 0x64, 0x30, 0xC8, 0x28, 0x04, 0xD8, 0xBD, 0xF9, + 0x22, 0x00, 0x64, 0x30, 0xC8, 0x28, 0x01, 0xD9, 0x01, 0x23, 0x00, 0xE0, 0x03, 0x23, 0x0A, 0xAA, + 0x08, 0xA9, 0x09, 0xA8, 0xFF, 0xF7, 0x57, 0xFF, 0x60, 0x88, 0xBD, 0xF8, 0x26, 0x10, 0x08, 0x44, + 0xAD, 0xF8, 0x2E, 0x00, 0x20, 0x88, 0xBD, 0xF8, 0x24, 0x10, 0x00, 0x24, 0x08, 0x44, 0xAD, 0xF8, + 0x2C, 0x00, 0x18, 0xE0, 0x04, 0xEB, 0xC4, 0x00, 0x07, 0xEB, 0xC0, 0x01, 0x0B, 0xA8, 0x0C, 0x31, + 0x06, 0xF0, 0x47, 0xFE, 0x40, 0x45, 0x0C, 0xDA, 0xD9, 0xF8, 0x04, 0x10, 0x0A, 0x68, 0x02, 0xEB, + 0x42, 0x02, 0x01, 0xEB, 0x42, 0x02, 0x50, 0x60, 0x54, 0x72, 0x15, 0x72, 0x08, 0x68, 0x40, 0x1C, + 0x08, 0x60, 0x64, 0x1C, 0xE4, 0xB2, 0x97, 0xF8, 0x38, 0x04, 0xA0, 0x42, 0xE2, 0xD8, 0x6D, 0x1C, + 0x6D, 0xB2, 0x96, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0x96, 0xDA, 0xD9, 0xF8, 0x04, 0x00, 0x4D, 0x46, + 0x01, 0x68, 0x00, 0x29, 0x7E, 0xD0, 0x00, 0xF0, 0x61, 0xF9, 0x00, 0x26, 0x4F, 0xF0, 0x04, 0x09, + 0x74, 0xE0, 0x00, 0xBF, 0x06, 0xEB, 0x46, 0x01, 0x00, 0xEB, 0x41, 0x00, 0x51, 0x46, 0x90, 0xF9, + 0x08, 0x40, 0x90, 0xF9, 0x09, 0xC0, 0x11, 0x98, 0x03, 0x68, 0x0A, 0xFA, 0x04, 0xF0, 0x03, 0x42, + 0x63, 0xD1, 0x12, 0x9A, 0xD2, 0xF8, 0x00, 0x80, 0x01, 0xFA, 0x0C, 0xF2, 0x18, 0xEA, 0x02, 0x0F, + 0x5B, 0xD1, 0x03, 0x43, 0x11, 0x98, 0x88, 0x46, 0x03, 0x60, 0x12, 0x98, 0x12, 0x99, 0x00, 0x23, + 0x00, 0x68, 0x10, 0x43, 0x08, 0x60, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x0C, 0xEB, + 0xCC, 0x00, 0x0B, 0xEB, 0x01, 0x14, 0x07, 0xEB, 0xC0, 0x02, 0x21, 0x46, 0x58, 0x46, 0xFF, 0xF7, + 0x47, 0xFE, 0x94, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x0C, 0xD0, 0x06, 0x28, + 0x10, 0xD0, 0x3A, 0xE0, 0x84, 0xF8, 0x41, 0x81, 0x09, 0xE0, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xF8, 0x05, 0x10, 0x00, 0xF4, 0x06, 0x10, 0x00, 0x00, 0x20, 0x84, 0xF8, 0x41, 0x01, 0x84, 0xF8, + 0x3E, 0x91, 0x2A, 0xE0, 0x84, 0xF8, 0x3E, 0x91, 0x94, 0xF8, 0x40, 0x00, 0x10, 0xF0, 0x06, 0x0F, + 0x23, 0xD0, 0x94, 0xF8, 0x42, 0x00, 0x40, 0x07, 0x1F, 0xD4, 0x97, 0x49, 0x95, 0x48, 0x09, 0x78, + 0xB0, 0xF9, 0x00, 0x00, 0x01, 0x29, 0x02, 0xD1, 0x94, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0x94, 0xF8, + 0x3F, 0x11, 0x03, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x0B, 0xD0, 0x0E, 0xE0, 0x8F, 0x48, 0xB4, 0xF9, + 0x54, 0x10, 0xB0, 0xF9, 0x00, 0x00, 0x06, 0xE0, 0x0C, 0xE0, 0x06, 0x20, 0x84, 0xF8, 0x3E, 0x01, + 0x03, 0xE0, 0xB4, 0xF9, 0x54, 0x10, 0x81, 0x42, 0xF7, 0xDB, 0x76, 0x1C, 0x68, 0x68, 0x01, 0x68, + 0xB1, 0x42, 0x87, 0xDC, 0x13, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x85, 0x48, 0x00, 0x21, 0x01, 0x70, + 0x41, 0x60, 0x81, 0x60, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x41, 0xF2, 0xFC, 0x30, + 0x2E, 0x21, 0x28, 0x44, 0x0C, 0xF0, 0x0F, 0xF8, 0x00, 0x24, 0x05, 0xF5, 0x80, 0x56, 0x01, 0x27, + 0x4F, 0xF0, 0x05, 0x08, 0x1C, 0xE0, 0x00, 0xBF, 0xD6, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x04, 0xF1, + 0x08, 0x42, 0x14, 0xD0, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x05, 0xEB, 0x00, 0x11, + 0x91, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x03, 0xD0, + 0x05, 0xE0, 0x81, 0xF8, 0x3E, 0x81, 0x02, 0xE0, 0x28, 0x46, 0xFF, 0xF7, 0xB3, 0xFC, 0x64, 0x1C, + 0x96, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0xDF, 0xDA, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x47, + 0x04, 0x46, 0x00, 0x25, 0x66, 0x48, 0x0E, 0x46, 0x00, 0x95, 0x01, 0x21, 0x00, 0x1D, 0x01, 0x95, + 0x03, 0xF0, 0x76, 0xFF, 0x62, 0x48, 0x05, 0x21, 0x08, 0x30, 0x03, 0xF0, 0x71, 0xFF, 0x41, 0xF2, + 0xFC, 0x30, 0x2E, 0x21, 0x20, 0x44, 0x0B, 0xF0, 0xCE, 0xFF, 0x5D, 0x4F, 0xFF, 0x22, 0x2D, 0x21, + 0xB8, 0x68, 0x0B, 0xF0, 0x9E, 0xFF, 0x3D, 0x70, 0x04, 0xF5, 0x80, 0x57, 0x4F, 0xF0, 0x01, 0x08, + 0xD7, 0xF8, 0xB0, 0x03, 0x58, 0xB3, 0x6B, 0x46, 0x01, 0xAA, 0x31, 0x46, 0x20, 0x46, 0xFF, 0xF7, + 0x72, 0xFE, 0x4F, 0xF0, 0x05, 0x09, 0x1E, 0xE0, 0xD7, 0xF8, 0xB0, 0x13, 0x08, 0xFA, 0x05, 0xF0, + 0x01, 0x42, 0x17, 0xD0, 0x01, 0x99, 0x08, 0x42, 0x14, 0xD1, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, + 0x40, 0x00, 0x04, 0xEB, 0x00, 0x11, 0x91, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x04, 0xD0, 0x04, 0x28, + 0x02, 0xD0, 0x02, 0x28, 0x03, 0xD0, 0x05, 0xE0, 0x81, 0xF8, 0x3E, 0x91, 0x02, 0xE0, 0x20, 0x46, + 0xFF, 0xF7, 0x60, 0xFC, 0x6D, 0x1C, 0x97, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0xDC, 0xDA, 0x00, 0x25, + 0x47, 0x46, 0x1A, 0xE0, 0x00, 0x99, 0x07, 0xFA, 0x05, 0xF0, 0x08, 0x42, 0x14, 0xD1, 0x20, 0x46, + 0xFF, 0xF7, 0x32, 0xFC, 0x00, 0x28, 0x0F, 0xDB, 0xC0, 0xEB, 0xC0, 0x01, 0x01, 0xEB, 0x41, 0x01, + 0x04, 0xEB, 0x01, 0x11, 0x05, 0xEB, 0xC5, 0x02, 0x81, 0xF8, 0x4A, 0x01, 0x06, 0xEB, 0xC2, 0x02, + 0x01, 0x23, 0x20, 0x46, 0xFF, 0xF7, 0x54, 0xFD, 0x6D, 0x1C, 0x96, 0xF8, 0x38, 0x04, 0xA8, 0x42, + 0xE0, 0xD8, 0x2F, 0x48, 0x01, 0x21, 0x00, 0x1D, 0x03, 0xF0, 0x22, 0xFF, 0x2C, 0x48, 0x05, 0x21, + 0x08, 0x30, 0x03, 0xF0, 0x1D, 0xFF, 0xBD, 0xE8, 0xFC, 0x87, 0x30, 0xB5, 0x28, 0x4A, 0x91, 0xF8, + 0x44, 0x51, 0x94, 0x68, 0x63, 0x5D, 0xFF, 0x2B, 0x05, 0xD1, 0x13, 0x78, 0x63, 0x55, 0x0F, 0x2B, + 0x01, 0xD2, 0x5B, 0x1C, 0x13, 0x70, 0x91, 0xF8, 0x44, 0x21, 0xA2, 0x5C, 0x81, 0xF8, 0x44, 0x21, + 0x00, 0xEB, 0x42, 0x02, 0x02, 0xF5, 0x80, 0x52, 0x91, 0xF8, 0x4A, 0x51, 0xB2, 0xF8, 0xFC, 0x33, + 0x01, 0x24, 0xAC, 0x40, 0x23, 0x43, 0xA2, 0xF8, 0xFC, 0x33, 0x91, 0xF8, 0x44, 0x11, 0x41, 0xF2, + 0x1A, 0x42, 0x10, 0x44, 0x0A, 0x5C, 0x52, 0x1C, 0x0A, 0x54, 0x30, 0xBD, 0x7C, 0xB5, 0x00, 0x21, + 0x1C, 0xE0, 0x01, 0xEB, 0x41, 0x03, 0x4A, 0x1C, 0x00, 0xEB, 0x43, 0x03, 0x12, 0xE0, 0x02, 0xEB, + 0x42, 0x04, 0x00, 0xEB, 0x44, 0x04, 0x5E, 0x68, 0x65, 0x68, 0xAE, 0x42, 0x09, 0xDD, 0x00, 0x96, + 0x1E, 0x89, 0xAD, 0xF8, 0x04, 0x60, 0x5D, 0x60, 0x25, 0x89, 0x1D, 0x81, 0x00, 0x9D, 0x65, 0x60, + 0x26, 0x81, 0x52, 0x1C, 0x04, 0x68, 0x94, 0x42, 0xE9, 0xDC, 0x49, 0x1C, 0x02, 0x68, 0x8A, 0x42, + 0xDF, 0xDC, 0x7C, 0xBD, 0x70, 0x06, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, + 0xF8, 0x05, 0x10, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x00, 0x22, 0x91, 0x46, 0x15, 0x46, 0x14, 0x46, + 0x00, 0x92, 0xFE, 0x4A, 0xFE, 0x4B, 0x12, 0x68, 0xB3, 0xF9, 0x00, 0xC0, 0xFD, 0x4B, 0x17, 0x8E, + 0x1E, 0x68, 0x67, 0x45, 0x60, 0xD1, 0x86, 0x46, 0xFB, 0x48, 0x02, 0xF1, 0x32, 0x0A, 0x8B, 0x46, + 0x90, 0xF8, 0x00, 0xC0, 0xF9, 0x48, 0x07, 0x78, 0x4D, 0xE0, 0x3A, 0x46, 0x43, 0xE0, 0x00, 0xBF, + 0x3A, 0xF8, 0x12, 0x10, 0x3E, 0xF8, 0x12, 0x00, 0x3B, 0xF8, 0x12, 0x30, 0x08, 0x1A, 0xC9, 0x1A, + 0x00, 0xB2, 0x0B, 0xB2, 0x00, 0x28, 0x01, 0xDB, 0x01, 0x46, 0x00, 0xE0, 0x41, 0x42, 0x49, 0x45, + 0x06, 0xDD, 0x00, 0x28, 0x01, 0xDB, 0x01, 0x46, 0x00, 0xE0, 0x41, 0x42, 0x0F, 0xFA, 0x81, 0xF9, + 0x19, 0x1A, 0x01, 0xD4, 0x88, 0x46, 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x08, 0xA8, 0x45, 0x05, 0xDD, + 0x00, 0x29, 0x01, 0xDB, 0x0D, 0x46, 0x00, 0xE0, 0x4D, 0x42, 0x2D, 0xB2, 0x00, 0x29, 0x00, 0xDA, + 0x49, 0x42, 0xB6, 0xF8, 0xE2, 0x83, 0x41, 0x45, 0x15, 0xDD, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, + 0x01, 0x1E, 0x00, 0xDA, 0x41, 0x42, 0x8B, 0x42, 0x02, 0xDD, 0x64, 0x1C, 0xA4, 0xB2, 0x0A, 0xE0, + 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0xB6, 0xF8, 0xE4, 0x13, 0x88, 0x42, 0x03, 0xDD, 0x4F, 0xF0, + 0x00, 0x0C, 0x64, 0x46, 0x01, 0xE0, 0x52, 0x1E, 0xBA, 0xD1, 0x0A, 0xEB, 0x47, 0x0A, 0x0E, 0xEB, + 0x47, 0x0E, 0x0B, 0xEB, 0x47, 0x0B, 0xBC, 0xF1, 0x01, 0x0C, 0xAE, 0xD2, 0x96, 0xF8, 0xE6, 0x03, + 0xA0, 0x42, 0x01, 0xD2, 0x01, 0x20, 0x00, 0x90, 0x96, 0xF8, 0xE7, 0x13, 0xCC, 0x48, 0x00, 0x9A, + 0x06, 0xF0, 0xB1, 0xFB, 0xCB, 0x49, 0x21, 0xF8, 0x25, 0x5F, 0x21, 0xF8, 0x02, 0x9C, 0x8C, 0x70, + 0xBD, 0xE8, 0xF8, 0x8F, 0x10, 0xB5, 0x0C, 0x46, 0xC3, 0x49, 0x09, 0x78, 0x4A, 0x00, 0x01, 0x46, + 0xC5, 0x48, 0x0B, 0xF0, 0xE7, 0xFD, 0xC1, 0x48, 0x21, 0x46, 0x00, 0x78, 0x42, 0x00, 0xC3, 0x48, + 0x0B, 0xF0, 0xE0, 0xFD, 0xC2, 0x49, 0x01, 0x20, 0x08, 0x70, 0x10, 0xBD, 0xB8, 0x49, 0x10, 0xB5, + 0xB1, 0xF9, 0x00, 0x10, 0x4A, 0x00, 0x01, 0x46, 0xBE, 0x48, 0x00, 0x68, 0x0B, 0xF0, 0xD2, 0xFD, + 0xBD, 0x49, 0x01, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x10, 0xB5, 0x01, 0x23, 0x0A, 0xE0, 0x00, 0xBF, + 0x30, 0xF9, 0x13, 0x40, 0x00, 0x2C, 0x00, 0xDA, 0x64, 0x42, 0x8C, 0x42, 0x01, 0xDD, 0x01, 0x20, + 0x10, 0xBD, 0x5B, 0x1C, 0x93, 0x42, 0xF3, 0xDB, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, + 0xAB, 0x48, 0x00, 0x24, 0x08, 0x38, 0xDF, 0xF8, 0x9C, 0x82, 0x44, 0x60, 0x04, 0x70, 0xD8, 0xF8, + 0x00, 0x00, 0x9A, 0x46, 0x27, 0x46, 0x90, 0xF8, 0xAB, 0x02, 0x26, 0x46, 0x25, 0x46, 0x40, 0x07, + 0x03, 0xD5, 0xAA, 0x48, 0x00, 0x68, 0x00, 0xF0, 0xAB, 0xF9, 0xD8, 0xF8, 0x00, 0x00, 0xDF, 0xF8, + 0x80, 0x92, 0x90, 0xF8, 0xE0, 0x03, 0xC0, 0x07, 0x0E, 0xD0, 0x03, 0x20, 0x09, 0xF0, 0xAB, 0xFD, + 0xA0, 0x48, 0x01, 0x68, 0x00, 0x98, 0xFF, 0xF7, 0x25, 0xFF, 0x04, 0x46, 0x11, 0x26, 0x03, 0x20, + 0x09, 0xF0, 0xBC, 0xFD, 0x14, 0xB1, 0x74, 0xE0, 0x89, 0xF8, 0x00, 0x50, 0x9C, 0x48, 0x01, 0x78, + 0x11, 0xB9, 0x40, 0x78, 0x00, 0x28, 0x6C, 0xD0, 0xFA, 0xF7, 0x74, 0xFD, 0xD8, 0xF8, 0x00, 0x00, + 0xDF, 0xF8, 0x60, 0xB2, 0x90, 0xF8, 0xE0, 0x03, 0x80, 0x07, 0x14, 0xD5, 0x96, 0x48, 0x00, 0x78, + 0x88, 0xB9, 0x96, 0x48, 0x00, 0x78, 0x70, 0xB9, 0x0B, 0xF0, 0xC6, 0xFE, 0x58, 0xB9, 0x94, 0x4A, + 0x94, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x35, 0xF9, 0x04, 0x00, 0x4F, 0xF0, 0x30, 0x06, + 0x4F, 0xF0, 0x01, 0x07, 0x0F, 0xD1, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE1, 0x03, 0xC0, 0x07, + 0x09, 0xD0, 0x8D, 0x4A, 0x8D, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x7D, 0xF8, 0x30, 0x26, + 0x04, 0x46, 0x01, 0x27, 0x01, 0xE0, 0x89, 0xF8, 0x01, 0x50, 0x7C, 0xB9, 0xD8, 0xF8, 0x00, 0x00, + 0x90, 0xF8, 0xE1, 0x03, 0x80, 0x07, 0x09, 0xD5, 0x83, 0x4A, 0x84, 0x49, 0xDB, 0xF8, 0x00, 0x00, + 0x00, 0xF0, 0xA5, 0xF8, 0x31, 0x26, 0x04, 0x46, 0x01, 0x27, 0x01, 0xE0, 0x89, 0xF8, 0x02, 0x50, + 0x2C, 0xBB, 0xD8, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xE0, 0x03, 0x40, 0x07, 0x1F, 0xD5, 0xB1, 0xF9, + 0xFD, 0x23, 0x69, 0x49, 0x79, 0x48, 0x78, 0x4C, 0x09, 0x78, 0x07, 0xF0, 0xC8, 0xF8, 0x06, 0x46, + 0xD8, 0xF8, 0x00, 0x00, 0xB0, 0xF9, 0xFD, 0x23, 0x64, 0x48, 0x01, 0x78, 0x20, 0x46, 0x07, 0xF0, + 0xBE, 0xF8, 0x40, 0xEA, 0x06, 0x02, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xFF, 0x13, 0x09, 0xF1, + 0x03, 0x00, 0x06, 0xF0, 0xD8, 0xFA, 0x21, 0x26, 0x04, 0x46, 0x01, 0x27, 0x01, 0xE0, 0x89, 0xF8, + 0x03, 0x50, 0x0B, 0xF0, 0x81, 0xFE, 0x01, 0x46, 0x69, 0x48, 0x01, 0x70, 0x4C, 0xB3, 0x6F, 0xB1, + 0x8A, 0xF8, 0x00, 0x50, 0x31, 0x46, 0x05, 0x20, 0x05, 0xF0, 0x84, 0xFD, 0x00, 0x98, 0xFF, 0xF7, + 0x2D, 0xFF, 0xDD, 0xE9, 0x01, 0x01, 0xFF, 0xF7, 0x15, 0xFF, 0x16, 0xE0, 0x01, 0x20, 0x8A, 0xF8, + 0x00, 0x00, 0x4F, 0x48, 0x08, 0x38, 0x06, 0x70, 0x41, 0x68, 0x41, 0xF0, 0x02, 0x01, 0x41, 0x60, + 0xD8, 0xF8, 0x00, 0x20, 0x92, 0xF8, 0x50, 0x32, 0xDB, 0x07, 0x03, 0xD1, 0x92, 0xF8, 0x80, 0x22, + 0xD2, 0x07, 0x02, 0xD0, 0x41, 0xF0, 0x08, 0x01, 0x41, 0x60, 0x01, 0x20, 0x04, 0xB0, 0xBD, 0xE8, + 0xF0, 0x9F, 0x8A, 0xF8, 0x00, 0x50, 0x00, 0x78, 0xF8, 0xE7, 0x41, 0x48, 0x00, 0x21, 0x08, 0x38, + 0x41, 0x60, 0x01, 0x70, 0x81, 0x60, 0x70, 0x47, 0x2D, 0xE9, 0xF7, 0x4F, 0xDF, 0xF8, 0xE4, 0x80, + 0x93, 0x46, 0x0B, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0x25, 0x2C, 0x46, 0x90, 0xF8, 0xEC, 0x73, + 0xB0, 0xF9, 0xE8, 0x63, 0xB0, 0xF9, 0xEA, 0xA3, 0x33, 0x48, 0x31, 0x46, 0x02, 0x78, 0x18, 0x46, + 0x00, 0xF0, 0x07, 0xF9, 0x81, 0x46, 0x31, 0x48, 0x31, 0x46, 0x02, 0x78, 0x58, 0x46, 0x00, 0xF0, + 0x00, 0xF9, 0x01, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xD0, 0x51, 0xB9, 0x28, 0x48, 0x51, 0x46, + 0xB0, 0xF9, 0x00, 0x20, 0x00, 0x98, 0x00, 0xF0, 0x0C, 0xF9, 0x04, 0x46, 0xB8, 0x42, 0x00, 0xD9, + 0x01, 0x25, 0xD8, 0xF8, 0x00, 0x00, 0x2A, 0x46, 0x90, 0xF8, 0xED, 0x13, 0x24, 0x48, 0x40, 0x1C, + 0x06, 0xF0, 0x61, 0xFA, 0x23, 0x49, 0x81, 0xF8, 0x31, 0x40, 0xBD, 0xE8, 0xFE, 0x8F, 0x2D, 0xE9, + 0xF0, 0x47, 0xDF, 0xF8, 0x70, 0x80, 0x84, 0x46, 0x0B, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x18, 0x49, + 0x00, 0x25, 0x90, 0xF8, 0xF2, 0x73, 0xB0, 0xF9, 0xF0, 0x63, 0x91, 0x46, 0x2C, 0x46, 0xB0, 0xF9, + 0xEE, 0x03, 0xB1, 0xF9, 0x00, 0x10, 0x06, 0xE0, 0x3C, 0xF9, 0x11, 0x20, 0x00, 0x2A, 0x00, 0xDA, + 0x52, 0x42, 0x82, 0x42, 0x13, 0xDC, 0x49, 0x1E, 0xF6, 0xD2, 0x0F, 0x48, 0x31, 0x46, 0x02, 0x78, + 0x18, 0x46, 0x00, 0xF0, 0xC9, 0xF8, 0x04, 0x46, 0x0C, 0x48, 0x31, 0x46, 0x02, 0x78, 0x48, 0x46, + 0x00, 0xF0, 0xC2, 0xF8, 0x20, 0x44, 0xC4, 0xB2, 0xBC, 0x42, 0x00, 0xD9, 0x01, 0x25, 0xD8, 0xF8, + 0x00, 0x00, 0x2A, 0x46, 0x90, 0xF8, 0xF3, 0x13, 0x05, 0x48, 0x2B, 0xE0, 0x24, 0x07, 0x10, 0x00, + 0xCA, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, + 0x0C, 0x06, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, + 0x51, 0x07, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, 0xE0, 0x06, 0x10, 0x00, + 0xEC, 0x06, 0x10, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xC5, 0x06, 0x10, 0x00, + 0x32, 0x24, 0x10, 0x00, 0x08, 0x24, 0x10, 0x00, 0x60, 0x0B, 0x01, 0x20, 0x36, 0x0B, 0x01, 0x20, + 0x52, 0x06, 0x10, 0x00, 0x80, 0x1C, 0x06, 0xF0, 0xF6, 0xF9, 0x52, 0x49, 0x81, 0xF8, 0x32, 0x40, + 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x5F, 0x4F, 0x4E, 0x83, 0x46, 0x00, 0x25, 0x30, 0x68, + 0x92, 0x46, 0x0B, 0x46, 0x90, 0xF8, 0xF5, 0x73, 0xB0, 0xF9, 0xF6, 0xC3, 0xB0, 0xF9, 0xFA, 0x93, + 0x4A, 0x48, 0x2C, 0x46, 0x00, 0x78, 0x18, 0xB1, 0x49, 0x48, 0x00, 0x78, 0x90, 0xB1, 0x1C, 0xE0, + 0x48, 0x48, 0x61, 0x46, 0x02, 0x78, 0x18, 0x46, 0xFF, 0xF7, 0x4E, 0xFE, 0x80, 0x46, 0x46, 0x48, + 0x61, 0x46, 0x02, 0x78, 0x50, 0x46, 0xFF, 0xF7, 0x47, 0xFE, 0x01, 0x46, 0xB8, 0xF1, 0x00, 0x0F, + 0x00, 0xD0, 0x51, 0xB9, 0x41, 0x48, 0x49, 0x46, 0xB0, 0xF9, 0x00, 0x20, 0x58, 0x46, 0x00, 0xF0, + 0x60, 0xF8, 0x04, 0x46, 0xB8, 0x42, 0x00, 0xD9, 0x01, 0x25, 0x30, 0x68, 0x2A, 0x46, 0x90, 0xF8, + 0xFC, 0x13, 0x3B, 0x48, 0x06, 0xF0, 0xB7, 0xF9, 0x32, 0x49, 0x81, 0xF8, 0x31, 0x40, 0x0E, 0xE7, + 0x2D, 0xE9, 0xF0, 0x41, 0x37, 0x4F, 0x39, 0x78, 0x00, 0x29, 0x30, 0xD0, 0x36, 0x49, 0x09, 0x78, + 0x00, 0x29, 0x2C, 0xD1, 0x2F, 0x49, 0x35, 0x4D, 0x0B, 0x78, 0x2F, 0x49, 0x6C, 0x0C, 0x0E, 0x78, + 0x0E, 0xE0, 0x31, 0x46, 0x08, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x11, 0x20, 0xAA, 0x42, 0x00, 0xDD, + 0x15, 0x46, 0xA2, 0x42, 0x00, 0xDA, 0x14, 0x46, 0x49, 0x1E, 0xF5, 0xD2, 0x00, 0xEB, 0x46, 0x00, + 0x5B, 0x1E, 0xEE, 0xD2, 0x20, 0x48, 0x01, 0x68, 0xB1, 0xF9, 0xC7, 0x02, 0xB1, 0xF9, 0xC9, 0x12, + 0x85, 0x42, 0x08, 0xDA, 0x48, 0x42, 0x84, 0x42, 0x05, 0xDD, 0x00, 0x20, 0x38, 0x70, 0x01, 0x46, + 0x08, 0x20, 0x05, 0xF0, 0x3F, 0xFC, 0x17, 0x48, 0x20, 0xF8, 0x44, 0x5F, 0x44, 0x80, 0xBD, 0xE8, + 0xF0, 0x81, 0x05, 0xE0, 0x30, 0xF9, 0x12, 0x30, 0x8B, 0x42, 0x01, 0xDD, 0x01, 0x20, 0x70, 0x47, + 0x52, 0x1E, 0xF7, 0xD2, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x03, 0x46, 0x00, 0x20, 0x05, 0xE0, + 0x33, 0xF9, 0x12, 0x40, 0x8C, 0x42, 0x01, 0xDD, 0x40, 0x1C, 0xC0, 0xB2, 0x52, 0x1E, 0xF7, 0xD2, + 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x09, 0xE0, 0x00, 0xBF, 0x34, 0xF9, 0x12, 0x30, + 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, 0x8B, 0x42, 0x01, 0xDD, 0x40, 0x1C, 0xC0, 0xB2, 0x52, 0x1E, + 0xF4, 0xD2, 0x10, 0xBD, 0xE6, 0x43, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, + 0x0C, 0x05, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, + 0x0D, 0x06, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0x2D, 0xE9, 0xFF, 0x4F, 0x87, 0xB0, 0x00, 0x20, 0x81, 0x46, 0x03, 0x90, 0x02, 0x90, 0x01, 0x90, + 0x6C, 0x48, 0x88, 0x46, 0x93, 0x46, 0x00, 0x68, 0xB0, 0xF8, 0xBA, 0x02, 0x06, 0x90, 0x89, 0x78, + 0x50, 0x68, 0x0B, 0xF0, 0xFD, 0xFC, 0x00, 0x90, 0x98, 0xF8, 0x02, 0x50, 0x98, 0xF8, 0x03, 0x00, + 0x05, 0x90, 0x32, 0xE0, 0x07, 0x98, 0x98, 0xF8, 0x00, 0x40, 0x00, 0xEB, 0xC5, 0x00, 0x04, 0x90, + 0x98, 0xF8, 0x01, 0xA0, 0x1F, 0xE0, 0x04, 0x98, 0x22, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67, + 0x01, 0x20, 0x0B, 0xF0, 0x20, 0xFB, 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x12, 0xD0, 0x00, 0x98, + 0x06, 0x99, 0x30, 0xF9, 0x14, 0x00, 0x88, 0x42, 0x0C, 0xDD, 0x02, 0x99, 0x81, 0x44, 0x04, 0xFB, + 0x00, 0x11, 0x02, 0x91, 0x01, 0x99, 0x05, 0xFB, 0x00, 0x10, 0x01, 0x90, 0x03, 0x98, 0x40, 0x1C, + 0x80, 0xB2, 0x03, 0x90, 0x64, 0x1C, 0xA2, 0x45, 0xDD, 0xDA, 0x4F, 0x49, 0x00, 0x98, 0x6D, 0x1C, + 0x09, 0x78, 0x00, 0xEB, 0x41, 0x00, 0x00, 0x90, 0x05, 0x98, 0xA8, 0x42, 0xCA, 0xDA, 0x49, 0x48, + 0x00, 0x25, 0x04, 0x68, 0x01, 0x98, 0xA1, 0x8E, 0xC2, 0x17, 0xA1, 0xFB, 0x00, 0x36, 0x05, 0xFB, + 0x00, 0x60, 0x01, 0xFB, 0x02, 0x02, 0x4F, 0xF6, 0xFF, 0x76, 0xA3, 0xFB, 0x06, 0x07, 0x02, 0xFB, + 0x06, 0x72, 0x03, 0xFB, 0x05, 0x21, 0x94, 0xF8, 0x31, 0x30, 0x30, 0x34, 0x5B, 0x1E, 0x89, 0xFB, + 0x03, 0x23, 0x0B, 0xF0, 0xF3, 0xFA, 0x72, 0x10, 0x80, 0x18, 0xB0, 0x46, 0x41, 0xF1, 0x00, 0x01, + 0x42, 0x46, 0x00, 0x23, 0x0B, 0xF0, 0xEA, 0xFA, 0x07, 0x46, 0x02, 0x98, 0x61, 0x88, 0xC2, 0x17, + 0xA1, 0xFB, 0x00, 0x36, 0x05, 0xFB, 0x00, 0x60, 0x01, 0xFB, 0x02, 0x01, 0x42, 0x46, 0xA3, 0xFB, + 0x02, 0x06, 0x01, 0xFB, 0x02, 0x61, 0x03, 0xFB, 0x05, 0x11, 0x23, 0x78, 0x5B, 0x1E, 0x89, 0xFB, + 0x03, 0x23, 0x0B, 0xF0, 0xD3, 0xFA, 0x47, 0xF6, 0xFF, 0x72, 0x80, 0x18, 0x41, 0xF1, 0x00, 0x01, + 0x42, 0x46, 0x00, 0x23, 0x0B, 0xF0, 0xCA, 0xFA, 0xCB, 0xF8, 0x1C, 0x90, 0x03, 0x99, 0xAB, 0xF8, + 0x28, 0x10, 0x0A, 0x99, 0x48, 0x60, 0x0A, 0x99, 0x0F, 0x60, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x10, 0xB5, 0x20, 0x49, 0x43, 0x68, 0x00, 0x22, 0x09, 0x68, 0x00, 0x2B, 0x01, 0xDA, 0x42, 0x60, + 0x03, 0xE0, 0x4C, 0x8E, 0xA3, 0x42, 0x00, 0xDD, 0x44, 0x60, 0x03, 0x68, 0x00, 0x2B, 0x01, 0xDA, + 0x02, 0x60, 0x10, 0xBD, 0x89, 0x8E, 0x8B, 0x42, 0xFB, 0xDD, 0x01, 0x60, 0x10, 0xBD, 0x7C, 0xB5, + 0x14, 0x46, 0x00, 0x25, 0x6B, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0x14, 0x48, 0x01, 0x78, 0x11, 0x48, + 0x29, 0xB1, 0x01, 0x68, 0x91, 0xF8, 0x07, 0x15, 0x09, 0x07, 0x00, 0xD5, 0x04, 0x25, 0x94, 0xF8, + 0x40, 0x10, 0x03, 0x29, 0x08, 0xD1, 0x00, 0x68, 0x90, 0xF8, 0x07, 0x05, 0xC0, 0x07, 0x03, 0xD0, + 0x29, 0x46, 0x68, 0x46, 0x01, 0xF0, 0xD2, 0xFC, 0x68, 0x46, 0xFF, 0xF7, 0xC9, 0xFF, 0x01, 0x98, + 0xE0, 0x81, 0x00, 0x98, 0xA0, 0x81, 0x94, 0xF8, 0x24, 0x00, 0xC0, 0x06, 0x01, 0xD4, 0xE0, 0x68, + 0x60, 0x61, 0x7C, 0xBD, 0x20, 0x07, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, + 0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x90, 0xF8, 0x02, 0x80, 0x0F, 0x46, 0x88, 0x68, 0x14, 0x46, + 0x01, 0x26, 0x41, 0x46, 0x0B, 0xF0, 0x1C, 0xFC, 0x81, 0x46, 0xA8, 0xF1, 0x01, 0x00, 0xC1, 0xB2, + 0xB8, 0x68, 0x0B, 0xF0, 0x15, 0xFC, 0x29, 0x78, 0x09, 0xEB, 0x41, 0x02, 0x32, 0xF9, 0x02, 0x2C, + 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, 0x11, 0x10, 0xA1, 0x42, 0x00, 0xDA, 0x00, 0x26, 0x69, 0x78, + 0x09, 0xEB, 0x41, 0x02, 0xB2, 0xF9, 0x02, 0x20, 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, 0x11, 0x00, + 0xA0, 0x42, 0x00, 0xDA, 0x00, 0x26, 0x95, 0xF8, 0x03, 0x80, 0xB8, 0x68, 0x41, 0x46, 0x0B, 0xF0, + 0xF7, 0xFB, 0x81, 0x46, 0x08, 0xF1, 0x01, 0x00, 0xC1, 0xB2, 0xB8, 0x68, 0x0B, 0xF0, 0xF0, 0xFB, + 0x29, 0x78, 0x09, 0xEB, 0x41, 0x02, 0x32, 0xF9, 0x02, 0x2C, 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, + 0x11, 0x10, 0xA1, 0x42, 0x00, 0xDA, 0x00, 0x26, 0x69, 0x78, 0x09, 0xEB, 0x41, 0x02, 0xB2, 0xF9, + 0x02, 0x20, 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, 0x11, 0x00, 0xA0, 0x42, 0x00, 0xDA, 0x00, 0x26, + 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x4F, 0xFB, 0x48, 0xDF, 0xF8, 0xEC, 0x83, + 0x92, 0x46, 0x04, 0x68, 0x97, 0xB0, 0x99, 0x46, 0x01, 0x22, 0x51, 0x46, 0xD8, 0xF8, 0x00, 0x00, + 0x01, 0xF0, 0xC8, 0xF9, 0xF6, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0x4D, 0x14, 0x11, 0x91, 0x90, 0xF8, + 0x4C, 0x04, 0x0A, 0x90, 0xF3, 0x48, 0x9A, 0xF8, 0x02, 0x70, 0x9A, 0xF8, 0x03, 0x60, 0x00, 0x78, + 0x9A, 0xF8, 0x00, 0xB0, 0x9A, 0xF8, 0x01, 0x50, 0x40, 0x1E, 0x87, 0x42, 0x01, 0xDA, 0x7F, 0x1C, + 0xFF, 0xB2, 0x0E, 0xB1, 0x76, 0x1E, 0xF6, 0xB2, 0xEB, 0x49, 0x09, 0x78, 0x49, 0x1E, 0x8B, 0x45, + 0x03, 0xDA, 0x0B, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0B, 0x0D, 0xB1, 0x6D, 0x1E, 0xED, 0xB2, + 0xB8, 0x1E, 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, 0x0B, 0xF0, 0x9A, 0xFB, 0x0B, 0x90, 0x78, 0x1E, + 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, 0x0B, 0xF0, 0x93, 0xFB, 0x04, 0x90, 0x39, 0x46, 0xD9, 0xF8, + 0x08, 0x00, 0x0B, 0xF0, 0x8D, 0xFB, 0x01, 0x90, 0x78, 0x1C, 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, + 0x0B, 0xF0, 0x86, 0xFB, 0x02, 0x90, 0xB8, 0x1C, 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, 0x0B, 0xF0, + 0x7F, 0xFB, 0x03, 0x90, 0x39, 0x46, 0x17, 0x98, 0x0B, 0xF0, 0x74, 0xFB, 0x08, 0x90, 0xCF, 0x48, + 0x39, 0x46, 0x00, 0x68, 0x0B, 0xF0, 0x7C, 0xFB, 0x86, 0x46, 0x00, 0x20, 0x7A, 0xB2, 0xCF, 0x4F, + 0x0C, 0x90, 0xB7, 0xE0, 0x4F, 0xFA, 0x8B, 0xF0, 0x94, 0xE0, 0x00, 0x21, 0x0E, 0xF8, 0x00, 0x10, + 0x08, 0x99, 0x18, 0x9B, 0x09, 0x5C, 0x99, 0x42, 0x75, 0xD1, 0xDF, 0xF8, 0x14, 0xC3, 0x01, 0x9B, + 0xDC, 0xF8, 0x00, 0xC0, 0x33, 0xF9, 0x10, 0x30, 0xBC, 0xF8, 0x4F, 0xC4, 0x63, 0x45, 0x6A, 0xDA, + 0x00, 0x21, 0x14, 0x91, 0x13, 0x91, 0x11, 0x99, 0x19, 0x44, 0x04, 0x9B, 0x09, 0xB2, 0x33, 0xF9, + 0x10, 0x30, 0x10, 0x93, 0x8B, 0x42, 0x06, 0xDD, 0x02, 0x9B, 0x33, 0xF9, 0x10, 0x30, 0x8B, 0x42, + 0x01, 0xDD, 0x01, 0x23, 0x13, 0x93, 0x01, 0x9B, 0x03, 0xEB, 0x40, 0x03, 0x33, 0xF9, 0x02, 0x8C, + 0x88, 0x45, 0x07, 0xDD, 0xB3, 0xF9, 0x02, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, 0x01, 0x0C, + 0xCD, 0xF8, 0x50, 0xC0, 0x01, 0x2A, 0x0F, 0xDD, 0xDD, 0xF8, 0x2C, 0xC0, 0x3C, 0xF9, 0x10, 0xC0, + 0x8C, 0x45, 0x09, 0xDD, 0xDD, 0xF8, 0x08, 0xC0, 0x3C, 0xF9, 0x10, 0xC0, 0x8C, 0x45, 0x03, 0xDD, + 0x4F, 0xF0, 0x01, 0x0C, 0xCD, 0xF8, 0x4C, 0xC0, 0xDF, 0xF8, 0x98, 0xC2, 0x9C, 0xF8, 0x00, 0xC0, + 0xAC, 0xF1, 0x02, 0x0C, 0x62, 0x45, 0x0D, 0xDA, 0xDD, 0xF8, 0x40, 0xC0, 0x8C, 0x45, 0x09, 0xDD, + 0xDD, 0xF8, 0x0C, 0xC0, 0x3C, 0xF9, 0x10, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, 0x01, 0x0C, + 0xCD, 0xF8, 0x4C, 0xC0, 0x01, 0x28, 0x0B, 0xDD, 0x33, 0xF9, 0x04, 0xCC, 0x8C, 0x45, 0x07, 0xDD, + 0xB3, 0xF9, 0x02, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, 0x01, 0x0C, 0xCD, 0xF8, 0x50, 0xC0, + 0xDF, 0xF8, 0x54, 0xC2, 0x9C, 0xF8, 0x00, 0xC0, 0xAC, 0xF1, 0x02, 0x0C, 0x60, 0x45, 0x05, 0xDA, + 0x88, 0x45, 0x03, 0xDD, 0xB3, 0xF9, 0x04, 0x30, 0x8B, 0x42, 0x12, 0xDC, 0x14, 0x99, 0x81, 0xB9, + 0x13, 0x99, 0x0D, 0xE0, 0xFF, 0xE7, 0x99, 0xB9, 0x01, 0x99, 0xB7, 0xF9, 0x00, 0x30, 0x31, 0xF9, + 0x10, 0x10, 0x99, 0x42, 0x0C, 0xDA, 0x86, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x41, 0x14, 0xC9, 0x07, + 0x31, 0xB1, 0x01, 0x21, 0x0E, 0xF8, 0x00, 0x10, 0x0C, 0x99, 0x49, 0x1C, 0x89, 0xB2, 0x0C, 0x91, + 0x40, 0x1C, 0x40, 0xB2, 0xA8, 0x42, 0x7F, 0xF7, 0x68, 0xAF, 0x7F, 0x48, 0x0B, 0x99, 0x0E, 0xF1, + 0x28, 0x0E, 0x00, 0x78, 0x01, 0xEB, 0x40, 0x01, 0x0B, 0x91, 0x04, 0x99, 0x01, 0xEB, 0x40, 0x01, + 0x04, 0x91, 0x01, 0x99, 0x01, 0xEB, 0x40, 0x01, 0x01, 0x91, 0x02, 0x99, 0x01, 0xEB, 0x40, 0x01, + 0x02, 0x91, 0x03, 0x99, 0x01, 0xEB, 0x40, 0x00, 0x03, 0x90, 0x08, 0x98, 0x28, 0x30, 0x52, 0x1C, + 0x52, 0xB2, 0x08, 0x90, 0xB2, 0x42, 0x7F, 0xF7, 0x45, 0xAF, 0x0A, 0x99, 0x0C, 0x98, 0x88, 0x42, + 0x2A, 0xD9, 0x00, 0x20, 0x84, 0xF8, 0x0E, 0x01, 0xDA, 0xF8, 0x00, 0x00, 0x20, 0x60, 0x67, 0x48, + 0x00, 0x23, 0x1A, 0x46, 0x21, 0x46, 0x00, 0x68, 0x01, 0xF0, 0xA6, 0xF9, 0x01, 0x25, 0x17, 0xE0, + 0x04, 0xEB, 0x85, 0x00, 0x06, 0x46, 0x51, 0x46, 0x00, 0xF0, 0x3F, 0xF9, 0x70, 0xB1, 0x04, 0xEB, + 0x45, 0x00, 0xB0, 0xF8, 0xB4, 0x10, 0x0A, 0x98, 0x81, 0x42, 0x07, 0xD9, 0x30, 0x46, 0xB7, 0xF9, + 0x00, 0x20, 0x49, 0x46, 0xFF, 0xF7, 0x64, 0xFE, 0x01, 0x28, 0x06, 0xD0, 0x6D, 0x1C, 0xED, 0xB2, + 0x94, 0xF8, 0x0E, 0x01, 0xA8, 0x42, 0xE3, 0xD2, 0x00, 0x20, 0x1B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x2D, 0xE9, 0xF8, 0x4F, 0x04, 0x46, 0x50, 0x48, 0xDF, 0xF8, 0x40, 0x81, 0x91, 0x46, 0x8B, 0x46, + 0x05, 0x68, 0x01, 0x22, 0x21, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x73, 0xF8, 0x00, 0x27, + 0xA6, 0x78, 0x4F, 0xF0, 0x01, 0x0A, 0x1D, 0xE0, 0x31, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x0B, 0xF0, + 0x6F, 0xFA, 0x00, 0x90, 0x31, 0x46, 0xDB, 0xF8, 0x08, 0x00, 0x0B, 0xF0, 0x61, 0xFA, 0x01, 0x46, + 0x20, 0x78, 0x52, 0x46, 0x09, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x10, 0xC0, 0xCC, 0x45, 0x02, 0xDA, + 0x00, 0x9B, 0x01, 0x27, 0x1A, 0x54, 0x40, 0x1C, 0xC0, 0xB2, 0x63, 0x78, 0x83, 0x42, 0xF3, 0xD2, + 0x76, 0x1C, 0xF6, 0xB2, 0xE0, 0x78, 0xB0, 0x42, 0xDE, 0xD2, 0x01, 0x2F, 0x2E, 0xD1, 0x00, 0x20, + 0x85, 0xF8, 0x0E, 0x01, 0x20, 0x68, 0x28, 0x60, 0x00, 0x23, 0x1A, 0x46, 0x29, 0x46, 0xD8, 0xF8, + 0x00, 0x00, 0x01, 0xF0, 0x41, 0xF9, 0x01, 0x26, 0xDF, 0xF8, 0xC4, 0x80, 0x1A, 0xE0, 0x00, 0xBF, + 0x05, 0xEB, 0x86, 0x07, 0x21, 0x46, 0x38, 0x46, 0x00, 0xF0, 0xD7, 0xF8, 0x80, 0xB1, 0x05, 0xEB, + 0x46, 0x00, 0xB0, 0xF8, 0xB4, 0x10, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x4C, 0x04, 0x81, 0x42, + 0x06, 0xD9, 0x38, 0x46, 0x4A, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0xFA, 0xFD, 0x01, 0x28, 0x06, 0xD0, + 0x76, 0x1C, 0xF6, 0xB2, 0x95, 0xF8, 0x0E, 0x01, 0xB0, 0x42, 0xE1, 0xD2, 0x00, 0x20, 0xBD, 0xE8, + 0xF8, 0x8F, 0x2D, 0xE9, 0xF0, 0x41, 0x1E, 0x4E, 0x0F, 0x46, 0x80, 0x46, 0x31, 0x68, 0x14, 0x46, + 0x1F, 0x48, 0x1D, 0x46, 0x9A, 0x69, 0xB1, 0xF8, 0x49, 0x34, 0x00, 0x78, 0x9A, 0x42, 0x10, 0xDC, + 0xEA, 0x8C, 0x04, 0x2A, 0x0D, 0xD9, 0x62, 0x78, 0x23, 0x78, 0x91, 0xF8, 0x4B, 0x14, 0xD2, 0x1A, + 0x52, 0x1C, 0x8A, 0x42, 0x05, 0xDC, 0xE2, 0x78, 0xA3, 0x78, 0xD2, 0x1A, 0x52, 0x1C, 0x8A, 0x42, + 0x02, 0xDD, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x28, 0xFB, 0xD1, 0x0F, 0x48, 0x29, 0x46, + 0xB0, 0xF9, 0x00, 0x20, 0x20, 0x46, 0xFF, 0xF7, 0x6B, 0xFF, 0x00, 0x28, 0xF2, 0xD1, 0x31, 0x68, + 0x91, 0xF8, 0x40, 0x14, 0x89, 0x07, 0xED, 0xD5, 0x2B, 0x46, 0x22, 0x46, 0x39, 0x46, 0x40, 0x46, + 0xBD, 0xE8, 0xF0, 0x41, 0x07, 0xE6, 0x00, 0x00, 0x48, 0x06, 0x10, 0x00, 0x30, 0x06, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x84, 0x06, 0x10, 0x00, + 0x10, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0xDF, 0xF8, 0x08, 0xB1, 0xDD, 0xF8, + 0x38, 0x90, 0x5F, 0xEA, 0x03, 0x08, 0x15, 0x46, 0x1D, 0xD4, 0x2C, 0x78, 0x0B, 0xEB, 0xC8, 0x0A, + 0x16, 0xE0, 0x00, 0xBF, 0x08, 0xF0, 0xFF, 0x01, 0x01, 0x98, 0x0B, 0xF0, 0xC1, 0xF9, 0x00, 0x90, + 0xDA, 0xE9, 0x00, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0xEC, 0xFF, 0x06, 0x40, + 0x0F, 0x40, 0x3E, 0x43, 0x02, 0xD1, 0x00, 0x98, 0x00, 0x21, 0x01, 0x55, 0x64, 0x1C, 0xE4, 0xB2, + 0x68, 0x78, 0xA0, 0x42, 0xE6, 0xD2, 0xB9, 0xF1, 0x00, 0x00, 0x1E, 0xDB, 0x02, 0x46, 0xAC, 0x78, + 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0xD7, 0xFF, 0x06, 0x46, 0x0F, 0x46, 0x4F, 0xF0, 0x00, 0x08, + 0x10, 0xE0, 0x21, 0x46, 0x01, 0x98, 0x0B, 0xF0, 0x9B, 0xF9, 0x0B, 0xEB, 0xC4, 0x01, 0x02, 0x46, + 0xD1, 0xE9, 0x00, 0x01, 0x30, 0x40, 0x39, 0x40, 0x08, 0x43, 0x01, 0xD1, 0x02, 0xF8, 0x09, 0x80, + 0x64, 0x1C, 0xE4, 0xB2, 0xE8, 0x78, 0xA0, 0x42, 0xEB, 0xD2, 0x05, 0xB0, 0xFE, 0xE6, 0x70, 0xB5, + 0x1E, 0x4B, 0x1D, 0x4A, 0x8C, 0x69, 0x1B, 0x68, 0x12, 0x78, 0xB3, 0xF8, 0x49, 0x54, 0xAC, 0x42, + 0x10, 0xDC, 0xCC, 0x8C, 0x04, 0x2C, 0x0D, 0xD9, 0x44, 0x78, 0x05, 0x78, 0x93, 0xF8, 0x4B, 0x34, + 0x64, 0x1B, 0x64, 0x1C, 0x9C, 0x42, 0x05, 0xDC, 0xC4, 0x78, 0x85, 0x78, 0x64, 0x1B, 0x64, 0x1C, + 0x9C, 0x42, 0x01, 0xDD, 0x00, 0x22, 0x06, 0xE0, 0x2A, 0xB9, 0x11, 0x4A, 0xB2, 0xF9, 0x00, 0x20, + 0xFF, 0xF7, 0xDE, 0xFE, 0x02, 0x46, 0x10, 0x46, 0x70, 0xBD, 0x02, 0x78, 0x0B, 0x78, 0x9A, 0x42, + 0x0B, 0xD9, 0x42, 0x78, 0x4B, 0x78, 0x9A, 0x42, 0x07, 0xD2, 0x82, 0x78, 0x8B, 0x78, 0x9A, 0x42, + 0x03, 0xD9, 0xC0, 0x78, 0xC9, 0x78, 0x88, 0x42, 0x01, 0xD3, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, + 0x70, 0x47, 0x00, 0x00, 0x48, 0x3F, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x6E, 0x06, 0x10, 0x00, 0x70, 0xB5, 0xFE, 0x4C, 0x00, 0xEB, 0x43, 0x05, 0x04, 0x9E, 0x00, 0xEB, + 0x83, 0x03, 0x86, 0xB1, 0x8E, 0x69, 0xA6, 0x60, 0xCE, 0x8C, 0x66, 0x80, 0x09, 0x68, 0x61, 0x61, + 0xB5, 0xF8, 0xB4, 0x10, 0xA1, 0x80, 0x19, 0x68, 0xE1, 0x60, 0x90, 0xF8, 0x0E, 0x01, 0x20, 0x70, + 0x10, 0x68, 0x20, 0x61, 0x70, 0xBD, 0xA6, 0x68, 0x8E, 0x61, 0x66, 0x88, 0xCE, 0x84, 0x66, 0x69, + 0x0E, 0x60, 0xA1, 0x88, 0xA5, 0xF8, 0xB4, 0x10, 0xE1, 0x68, 0x19, 0x60, 0x21, 0x78, 0x80, 0xF8, + 0x0E, 0x11, 0x20, 0x69, 0x10, 0x60, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0xE9, 0x48, + 0x0F, 0x46, 0xE9, 0x4D, 0x01, 0x78, 0x1C, 0x46, 0x16, 0x46, 0x09, 0xB9, 0x40, 0x78, 0xD8, 0xB1, + 0x28, 0x68, 0x90, 0xF8, 0x30, 0x02, 0x00, 0x07, 0x05, 0xD5, 0x39, 0x46, 0x40, 0x46, 0xF9, 0xF7, + 0xAC, 0xFA, 0x00, 0x28, 0x41, 0xD0, 0x28, 0x68, 0x90, 0xF8, 0x30, 0x02, 0x00, 0x06, 0x0B, 0xD5, + 0xDE, 0x48, 0x00, 0x78, 0x01, 0x28, 0x07, 0xD0, 0xDD, 0x48, 0x00, 0x78, 0x20, 0xB1, 0x30, 0x46, + 0xF9, 0xF7, 0xF5, 0xFA, 0x00, 0x28, 0x30, 0xD0, 0xDA, 0x4B, 0x32, 0x46, 0x39, 0x46, 0x40, 0x46, + 0x00, 0xF0, 0x9F, 0xFE, 0x00, 0x28, 0x28, 0xD0, 0x94, 0xF8, 0x40, 0x00, 0x03, 0x28, 0x08, 0xD1, + 0x29, 0x68, 0xE0, 0x8C, 0x91, 0xF8, 0x07, 0x13, 0x88, 0x42, 0x02, 0xD9, 0x04, 0x20, 0x84, 0xF8, + 0x40, 0x00, 0x30, 0x68, 0xC4, 0xF8, 0x36, 0x00, 0x04, 0xF1, 0x44, 0x02, 0x51, 0x1E, 0x30, 0x46, + 0xF8, 0xF7, 0x03, 0xFE, 0x22, 0x46, 0x31, 0x46, 0xCA, 0x48, 0x00, 0xF0, 0x9C, 0xFD, 0x31, 0x46, + 0xC8, 0x48, 0x00, 0xF0, 0x17, 0xFE, 0x22, 0x46, 0x31, 0x46, 0xC6, 0x48, 0xFF, 0xF7, 0x67, 0xFC, + 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFE, 0xF7, 0x63, 0xBC, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, + 0xF0, 0x41, 0x0D, 0x46, 0x1F, 0x46, 0x16, 0x46, 0x04, 0x46, 0x48, 0x21, 0x0A, 0xF0, 0xC3, 0xFF, + 0x00, 0x20, 0x84, 0xF8, 0x40, 0x00, 0xBC, 0x48, 0x00, 0x68, 0x60, 0x60, 0xA0, 0x60, 0x06, 0xEB, + 0x45, 0x00, 0x84, 0xF8, 0x42, 0x50, 0x30, 0xF8, 0xB4, 0x1F, 0x61, 0x85, 0x00, 0x88, 0xE0, 0x84, + 0x06, 0xEB, 0x85, 0x00, 0x00, 0x68, 0xC4, 0xF8, 0x3A, 0x00, 0xAD, 0x48, 0x81, 0x69, 0x21, 0x60, + 0x01, 0x21, 0xA9, 0x40, 0x39, 0x42, 0xD8, 0xD0, 0x40, 0x6A, 0x20, 0x60, 0xD5, 0xE7, 0x2D, 0xE9, + 0xF0, 0x47, 0x89, 0x46, 0x1C, 0x46, 0x16, 0x46, 0xAC, 0x4D, 0x03, 0xF1, 0x3E, 0x08, 0x91, 0x78, + 0x0B, 0xF0, 0x80, 0xF8, 0x07, 0x46, 0xB1, 0x78, 0x60, 0x68, 0x0B, 0xF0, 0x81, 0xF8, 0x02, 0x46, + 0x00, 0x20, 0xA0, 0x61, 0xB1, 0x78, 0x1F, 0xE0, 0x30, 0x78, 0x13, 0xE0, 0x17, 0xF8, 0x00, 0xC0, + 0xCC, 0x45, 0x0D, 0xD1, 0x32, 0xF9, 0x10, 0x30, 0xD4, 0xF8, 0x18, 0xC0, 0xAB, 0x42, 0x9C, 0x44, + 0xC4, 0xF8, 0x18, 0xC0, 0x04, 0xDD, 0x88, 0xF8, 0x00, 0x00, 0x1D, 0x46, 0x88, 0xF8, 0x01, 0x10, + 0x40, 0x1C, 0xC0, 0xB2, 0x73, 0x78, 0x83, 0x42, 0xE8, 0xD2, 0x99, 0x48, 0x49, 0x1C, 0xC9, 0xB2, + 0x00, 0x78, 0x28, 0x37, 0x02, 0xEB, 0x40, 0x02, 0xF0, 0x78, 0x88, 0x42, 0xDC, 0xD2, 0x65, 0x86, + 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0x0C, 0x46, 0x1E, 0x46, 0x99, 0x78, + 0xDD, 0xF8, 0x40, 0x80, 0x0E, 0x9D, 0x0B, 0xF0, 0x53, 0xF8, 0x00, 0x90, 0xB1, 0x78, 0x20, 0x46, + 0x0B, 0xF0, 0x40, 0xF8, 0x83, 0x46, 0xB1, 0x78, 0xD8, 0xF8, 0x04, 0x00, 0x0B, 0xF0, 0x40, 0xF8, + 0x81, 0x46, 0x88, 0x48, 0x4F, 0xF0, 0x00, 0x0A, 0xC8, 0xF8, 0x18, 0xA0, 0x00, 0x68, 0x28, 0x60, + 0xB7, 0x78, 0x41, 0xE0, 0x34, 0x78, 0x31, 0xE0, 0x1B, 0xF8, 0x04, 0x10, 0x03, 0x98, 0x81, 0x42, + 0x2A, 0xD1, 0x39, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x81, 0x42, 0x22, 0xDD, 0x00, 0x99, 0x03, 0x98, + 0x08, 0x55, 0x29, 0x78, 0x20, 0x46, 0x05, 0xF0, 0xC5, 0xFB, 0x28, 0x70, 0x69, 0x78, 0x20, 0x46, + 0x05, 0xF0, 0xC4, 0xFB, 0x68, 0x70, 0xA9, 0x78, 0x38, 0x46, 0x05, 0xF0, 0xBB, 0xFB, 0xA8, 0x70, + 0xE9, 0x78, 0x38, 0x46, 0x05, 0xF0, 0xBA, 0xFB, 0xE8, 0x70, 0x0A, 0xF1, 0x01, 0x00, 0x1F, 0xFA, + 0x80, 0xFA, 0x39, 0xF9, 0x14, 0x00, 0xD8, 0xF8, 0x18, 0x10, 0x01, 0x44, 0xC8, 0xF8, 0x18, 0x10, + 0x02, 0xE0, 0x00, 0x99, 0x00, 0x20, 0x08, 0x55, 0x64, 0x1C, 0xE4, 0xB2, 0x70, 0x78, 0xA0, 0x42, + 0xCA, 0xD2, 0x00, 0x98, 0x66, 0x49, 0x28, 0x30, 0x00, 0x90, 0x09, 0x78, 0x7F, 0x1C, 0x0B, 0xF1, + 0x28, 0x0B, 0x09, 0xEB, 0x41, 0x09, 0xFF, 0xB2, 0xF0, 0x78, 0xB8, 0x42, 0xBA, 0xD2, 0xA8, 0xF8, + 0x26, 0xA0, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xFF, 0x41, 0x17, 0x46, 0x0A, 0xAA, + 0x80, 0x46, 0x92, 0xE8, 0x31, 0x00, 0x5C, 0x4A, 0x1E, 0x46, 0xB2, 0xF9, 0x00, 0x20, 0x82, 0x42, + 0x02, 0xDB, 0x00, 0x20, 0x04, 0xB0, 0x20, 0xE7, 0x03, 0xAA, 0xCD, 0xE9, 0x00, 0x20, 0x02, 0x94, + 0x3A, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x7E, 0xFF, 0x01, 0x21, 0x28, 0x68, 0xB9, 0x40, 0x08, 0x43, + 0x28, 0x60, 0xC4, 0xF8, 0x00, 0x80, 0xE0, 0x8C, 0x10, 0xB1, 0x03, 0x98, 0x30, 0x60, 0xE8, 0xE7, + 0x01, 0x20, 0xE7, 0xE7, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0x90, 0x46, 0x0E, 0x9C, 0x8B, 0x46, + 0x04, 0xEB, 0x88, 0x00, 0x94, 0xF8, 0x0E, 0x71, 0xDD, 0xF8, 0x40, 0xA0, 0x00, 0x68, 0x1E, 0x46, + 0x20, 0x60, 0x01, 0x23, 0x21, 0x46, 0x58, 0x46, 0x00, 0xF0, 0xB6, 0xFE, 0x01, 0x98, 0x58, 0x45, + 0x1F, 0xD0, 0xB5, 0x78, 0x1A, 0xE0, 0x29, 0x46, 0x01, 0x98, 0x0A, 0xF0, 0xB1, 0xFF, 0x81, 0x46, + 0x29, 0x46, 0x58, 0x46, 0x0A, 0xF0, 0xAC, 0xFF, 0x01, 0x46, 0x30, 0x78, 0x09, 0xE0, 0x00, 0xBF, + 0x19, 0xF8, 0x00, 0x30, 0x43, 0x45, 0x02, 0xD1, 0x0B, 0x5C, 0x09, 0xF8, 0x00, 0x30, 0x40, 0x1C, + 0xC0, 0xB2, 0x72, 0x78, 0x82, 0x42, 0xF3, 0xD2, 0x6D, 0x1C, 0xED, 0xB2, 0xF0, 0x78, 0xA8, 0x42, + 0xE1, 0xD2, 0x94, 0xF8, 0x0E, 0x01, 0x00, 0x25, 0x01, 0x21, 0xB8, 0x42, 0x12, 0xD0, 0x11, 0x98, + 0x78, 0xB1, 0x7F, 0x1C, 0xF8, 0xB2, 0x08, 0xE0, 0xDA, 0xF8, 0x00, 0x20, 0x01, 0xFA, 0x00, 0xF3, + 0x1A, 0x43, 0x40, 0x1C, 0xC0, 0xB2, 0xCA, 0xF8, 0x00, 0x20, 0x94, 0xF8, 0x0E, 0x21, 0x82, 0x42, + 0xF2, 0xD2, 0x01, 0x25, 0x00, 0x91, 0x43, 0x46, 0x52, 0x46, 0x20, 0x46, 0x0F, 0x99, 0xFF, 0xF7, + 0x31, 0xFE, 0x28, 0x46, 0x7D, 0xE7, 0x10, 0xB5, 0x17, 0x4A, 0x20, 0x4C, 0x13, 0x68, 0x64, 0x78, + 0x93, 0xF8, 0x06, 0x23, 0x4C, 0xB1, 0x91, 0xF8, 0x24, 0x10, 0x09, 0x07, 0x02, 0xD5, 0x93, 0xF8, + 0x09, 0x13, 0x01, 0xE0, 0x93, 0xF8, 0x08, 0x13, 0x0A, 0x44, 0x90, 0x42, 0x01, 0xD9, 0x01, 0x20, + 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x1C, 0x46, 0x90, 0x46, 0x89, 0x46, + 0x82, 0x46, 0x01, 0xF0, 0x41, 0xF8, 0x08, 0x4F, 0xE1, 0x8C, 0x38, 0x68, 0x90, 0xF8, 0x0E, 0x23, + 0x91, 0x42, 0x7C, 0xD8, 0x03, 0x21, 0x84, 0xF8, 0x40, 0x10, 0x00, 0x25, 0x18, 0xE0, 0x00, 0x00, + 0x14, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x0E, 0x05, 0x10, 0x00, + 0xC0, 0x06, 0x10, 0x00, 0xA0, 0x3E, 0x10, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0xBA, 0x06, 0x10, 0x00, 0x52, 0x6C, 0x01, 0x00, 0x76, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0x90, 0xF8, 0xE0, 0x12, 0x8A, 0x07, 0x01, 0xD4, 0x49, 0x07, 0x00, 0xD5, 0x01, 0x25, 0xFF, 0x4A, + 0xB0, 0xF8, 0x0A, 0x13, 0xFE, 0x4E, 0x52, 0x78, 0x1A, 0xB1, 0xB2, 0x79, 0x0A, 0xB9, 0xB0, 0xF8, + 0x0C, 0x13, 0xA2, 0x8D, 0x8A, 0x42, 0x02, 0xD2, 0xFA, 0x49, 0x09, 0x78, 0x21, 0xB1, 0x61, 0x8D, + 0x03, 0x29, 0x06, 0xD2, 0x00, 0x25, 0x29, 0xE0, 0x61, 0x8D, 0x00, 0x25, 0x03, 0x29, 0xF9, 0xD3, + 0x24, 0xE0, 0x1D, 0xB3, 0x31, 0x79, 0x79, 0xB1, 0x90, 0xF8, 0x40, 0x04, 0x40, 0x07, 0x0B, 0xD5, + 0x21, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x7B, 0xFD, 0xEF, 0x49, 0x08, 0x70, 0x20, 0xB1, 0xA0, 0x8C, + 0x40, 0xF0, 0x80, 0x00, 0xA0, 0x84, 0xE5, 0xE7, 0x70, 0x79, 0x78, 0xB1, 0xEB, 0x48, 0xEC, 0x49, + 0xB0, 0xF9, 0x00, 0x00, 0xB1, 0xF9, 0x00, 0x10, 0x88, 0x42, 0x07, 0xDB, 0x23, 0x46, 0x42, 0x46, + 0x49, 0x46, 0x50, 0x46, 0x02, 0xF0, 0xD3, 0xF9, 0x01, 0x28, 0x04, 0xD0, 0xA0, 0x8C, 0x10, 0xF4, + 0xC0, 0x7F, 0x19, 0xD1, 0x04, 0xE0, 0xA0, 0x8C, 0x40, 0xF4, 0x80, 0x70, 0xA0, 0x84, 0x13, 0xE0, + 0x95, 0xB1, 0x38, 0x68, 0x90, 0xF8, 0xE0, 0x02, 0xC0, 0x07, 0x03, 0xD0, 0x21, 0x46, 0x40, 0x46, + 0x01, 0xF0, 0x95, 0xF9, 0x23, 0x46, 0x42, 0x46, 0x49, 0x46, 0x50, 0x46, 0x00, 0xE0, 0x0A, 0xE0, + 0xBD, 0xE8, 0xF0, 0x47, 0x02, 0xF0, 0xA8, 0xB8, 0x23, 0x46, 0x42, 0x46, 0x49, 0x46, 0x50, 0x46, + 0xBD, 0xE8, 0xF0, 0x47, 0xA8, 0xE5, 0x04, 0x20, 0x84, 0xF8, 0x40, 0x00, 0xF4, 0xE7, 0x2D, 0xE9, + 0xFF, 0x4F, 0xD0, 0x48, 0x87, 0xB0, 0xDF, 0xF8, 0x28, 0xB3, 0xB0, 0xF9, 0x00, 0x80, 0x0C, 0x46, + 0x00, 0x26, 0x14, 0x98, 0x9B, 0xF8, 0x04, 0x10, 0xDF, 0xF8, 0x2C, 0xA3, 0x01, 0x27, 0x15, 0x46, + 0x87, 0x40, 0xB1, 0x46, 0xD1, 0xB3, 0xC9, 0x48, 0xC5, 0x4A, 0xB0, 0xF9, 0x00, 0x10, 0xB2, 0xF9, + 0x00, 0x20, 0x91, 0x42, 0x32, 0xDA, 0x2A, 0x68, 0x3A, 0x42, 0x2F, 0xD1, 0xE2, 0x8C, 0x04, 0x2A, + 0x2C, 0xD9, 0x8D, 0xE8, 0x32, 0x00, 0x0A, 0x9B, 0x14, 0x9A, 0xDA, 0xF8, 0x18, 0x10, 0xDA, 0xF8, + 0x24, 0x00, 0xFF, 0xF7, 0xA1, 0xFE, 0x06, 0x00, 0x20, 0xD1, 0x23, 0x46, 0x20, 0x68, 0x0A, 0x9A, + 0x14, 0x99, 0xFF, 0xF7, 0x6E, 0xFC, 0xB4, 0x49, 0x08, 0x70, 0xA0, 0xB1, 0x70, 0x1E, 0x8D, 0xF8, + 0x10, 0x00, 0x8D, 0xF8, 0x14, 0x00, 0xB6, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x41, 0x04, 0x80, 0x07, + 0x05, 0xD5, 0x05, 0xAA, 0x04, 0xA9, 0x0A, 0x98, 0xF8, 0xF7, 0x13, 0xFC, 0x90, 0xB3, 0xA0, 0x8C, + 0x40, 0xF0, 0x80, 0x00, 0xA0, 0x84, 0xAD, 0x48, 0xB0, 0xF9, 0x00, 0x80, 0x9B, 0xF8, 0x05, 0x00, + 0x38, 0xB3, 0x94, 0xF8, 0x24, 0x00, 0x00, 0x06, 0x4F, 0xD4, 0xA4, 0x48, 0xA4, 0x4A, 0xB0, 0xF9, + 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x47, 0xDA, 0x83, 0x46, 0x41, 0x45, 0x17, 0xD0, + 0x28, 0x68, 0x38, 0x42, 0x07, 0xD0, 0xCD, 0xF8, 0x00, 0x90, 0x2A, 0x46, 0x21, 0x46, 0x14, 0x9B, + 0x07, 0x98, 0xFF, 0xF7, 0x0F, 0xFD, 0xBB, 0xF9, 0x00, 0x00, 0x8D, 0xE8, 0x31, 0x00, 0x0A, 0x9B, + 0x14, 0x9A, 0xDA, 0xF8, 0x18, 0x10, 0xDA, 0xF8, 0x24, 0x00, 0xFF, 0xF7, 0x55, 0xFE, 0x06, 0x46, + 0xFE, 0xB1, 0x2A, 0xE0, 0xFF, 0xE7, 0x97, 0x49, 0x9D, 0xF9, 0x10, 0x30, 0x01, 0xF8, 0x36, 0x3F, + 0x9D, 0xF9, 0x14, 0x00, 0x48, 0x70, 0x00, 0x90, 0x20, 0x68, 0x0A, 0x9A, 0x07, 0x99, 0xFF, 0xF7, + 0x61, 0xFC, 0x07, 0x99, 0x04, 0xF1, 0x3A, 0x03, 0x8D, 0xE8, 0x32, 0x02, 0x21, 0x68, 0x14, 0x9A, + 0xDA, 0xF8, 0x18, 0x00, 0xFF, 0xF7, 0x5E, 0xFE, 0x00, 0x28, 0xB4, 0xD0, 0x01, 0x20, 0x0B, 0xB0, + 0x30, 0xE6, 0x23, 0x46, 0x20, 0x68, 0x0A, 0x9A, 0x14, 0x99, 0x02, 0xF0, 0x08, 0xF9, 0x01, 0x28, + 0x03, 0xD1, 0xA0, 0x8C, 0x40, 0xF4, 0x80, 0x70, 0xA0, 0x84, 0xA0, 0x8C, 0x10, 0xF4, 0xC0, 0x7F, + 0x0A, 0xD1, 0x28, 0x68, 0x38, 0x42, 0x07, 0xD0, 0xCD, 0xF8, 0x00, 0x90, 0x2A, 0x46, 0x21, 0x46, + 0x14, 0x9B, 0x07, 0x98, 0xFF, 0xF7, 0xC6, 0xFC, 0x30, 0x46, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, + 0x79, 0x49, 0xDF, 0xF8, 0xCC, 0x81, 0xE5, 0xB0, 0xB1, 0xF9, 0x00, 0x10, 0xB8, 0xF9, 0x00, 0x00, + 0x00, 0x27, 0xCD, 0xE9, 0x60, 0x01, 0x70, 0x48, 0xBA, 0x46, 0xB9, 0x46, 0x3D, 0x46, 0x01, 0x21, + 0x1C, 0x30, 0x02, 0xF0, 0xE7, 0xFC, 0x6C, 0x48, 0x01, 0x21, 0x24, 0x30, 0x02, 0xF0, 0xE2, 0xFC, + 0x69, 0x48, 0x02, 0x21, 0x20, 0x30, 0x02, 0xF0, 0xDD, 0xFC, 0x02, 0x21, 0x6B, 0x48, 0x02, 0xF0, + 0x8F, 0xFC, 0x04, 0x21, 0x6A, 0x48, 0x02, 0xF0, 0x8B, 0xFC, 0x63, 0x4C, 0x4F, 0xF4, 0x66, 0x76, + 0x31, 0x46, 0xE0, 0x69, 0x0A, 0xF0, 0xC5, 0xFC, 0x31, 0x46, 0x60, 0x6A, 0x0A, 0xF0, 0xC1, 0xFC, + 0x64, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0x41, 0x00, 0x20, 0x6A, 0x0A, 0xF0, 0xBA, 0xFC, 0x31, 0x46, + 0x61, 0x48, 0x0A, 0xF0, 0xB6, 0xFC, 0x4F, 0xF0, 0x00, 0x0B, 0x5E, 0x46, 0x84, 0xF8, 0x01, 0xB0, + 0xF8, 0xF7, 0x0F, 0xFF, 0xF8, 0xF7, 0xC4, 0xFA, 0x5C, 0x48, 0x8D, 0xF8, 0x72, 0x61, 0x01, 0x23, + 0x00, 0x68, 0x19, 0x90, 0x00, 0x22, 0x19, 0xA9, 0xA0, 0x69, 0x00, 0xF0, 0xB5, 0xFC, 0x58, 0x48, + 0x5E, 0x96, 0x00, 0x24, 0xB0, 0xF9, 0x00, 0x10, 0xB8, 0xF9, 0x00, 0x00, 0x05, 0xF0, 0x4A, 0xF9, + 0x0F, 0xFA, 0x80, 0xF8, 0x9D, 0xF8, 0x72, 0x01, 0x01, 0x28, 0x02, 0xD9, 0x42, 0x49, 0x81, 0xF8, + 0x00, 0xB0, 0x01, 0x26, 0xF1, 0xE0, 0x19, 0xA8, 0x00, 0xEB, 0x86, 0x00, 0x05, 0x90, 0x19, 0xAA, + 0x31, 0x46, 0x07, 0xA8, 0x5E, 0x9B, 0xFF, 0xF7, 0xDA, 0xFC, 0x07, 0xAB, 0x31, 0x46, 0x05, 0x9A, + 0x07, 0x98, 0xFF, 0xF7, 0xFC, 0xFC, 0x01, 0x20, 0x00, 0x90, 0x33, 0x46, 0x5E, 0xAA, 0x07, 0xA9, + 0x19, 0xA8, 0xFF, 0xF7, 0x47, 0xFC, 0x0D, 0xF1, 0x5A, 0x00, 0x00, 0xF0, 0xAD, 0xFA, 0x78, 0xB1, + 0xBD, 0xF8, 0x40, 0x00, 0x40, 0xF0, 0x01, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0x07, 0xA8, 0x00, 0xF0, + 0x18, 0xFC, 0x28, 0xB1, 0x3B, 0x48, 0x34, 0x49, 0x00, 0x88, 0x08, 0x80, 0x2C, 0x49, 0x08, 0x80, + 0x28, 0x48, 0x00, 0x78, 0x38, 0xB1, 0xBD, 0xF8, 0x40, 0x00, 0x10, 0xF0, 0x06, 0x0F, 0x02, 0xD1, + 0x35, 0x48, 0x00, 0x68, 0x08, 0x90, 0x05, 0x98, 0x00, 0xF0, 0xA0, 0xFA, 0x28, 0xB1, 0xBD, 0xF8, + 0x40, 0x00, 0x40, 0xF0, 0x08, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0xBD, 0xF9, 0x4E, 0x10, 0x41, 0x45, + 0x7E, 0xDD, 0x00, 0x96, 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0x05, 0x9B, 0xFF, 0xF7, 0x97, 0xFE, + 0x00, 0x28, 0x76, 0xD1, 0x01, 0x20, 0xB0, 0x40, 0x5E, 0x99, 0x03, 0x90, 0x08, 0x42, 0x67, 0xD1, + 0xBD, 0xF8, 0x40, 0x00, 0x10, 0xF4, 0xC0, 0x7F, 0x62, 0xD1, 0x15, 0x48, 0x5E, 0xAA, 0x07, 0xA9, + 0xB0, 0xF9, 0x00, 0x00, 0x8D, 0xE8, 0x07, 0x00, 0x13, 0x48, 0x32, 0x46, 0x05, 0x9B, 0x81, 0x69, + 0x40, 0x6A, 0xFF, 0xF7, 0x49, 0xFD, 0x5E, 0x9A, 0x03, 0x99, 0x01, 0x90, 0x11, 0x42, 0x4D, 0xD0, + 0x0F, 0x49, 0xBD, 0xF8, 0x42, 0x20, 0x09, 0x68, 0x91, 0xF8, 0x0E, 0x33, 0x9A, 0x42, 0x2E, 0xD8, + 0x91, 0xF8, 0xE0, 0x12, 0x8A, 0x07, 0x41, 0xD4, 0x49, 0x07, 0x27, 0xE0, 0x4C, 0x07, 0x10, 0x00, + 0xEC, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x82, 0x06, 0x10, 0x00, + 0x6E, 0x06, 0x10, 0x00, 0x76, 0x06, 0x10, 0x00, 0x14, 0x06, 0x10, 0x00, 0x84, 0x06, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x70, 0x06, 0x10, 0x00, 0x3C, 0x06, 0x10, 0x00, + 0x48, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0xB4, 0x18, 0x01, 0x20, 0x64, 0x06, 0x10, 0x00, + 0x88, 0x06, 0x10, 0x00, 0x7E, 0x06, 0x10, 0x00, 0xE0, 0x06, 0x10, 0x00, 0x16, 0xD4, 0x01, 0x23, + 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0x8D, 0xE8, 0x0F, 0x00, 0xFF, 0x48, 0x0D, 0xF1, 0x56, 0x03, + 0x32, 0x46, 0x41, 0x6A, 0x80, 0x69, 0xFF, 0xF7, 0x25, 0xFD, 0x01, 0x90, 0x01, 0x20, 0x00, 0x90, + 0x33, 0x46, 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0xFF, 0xF7, 0xA4, 0xFB, 0x01, 0x98, 0x80, 0xB9, + 0xBD, 0xF8, 0x42, 0x00, 0x07, 0xA9, 0xFF, 0xF7, 0x6E, 0xFD, 0x50, 0xB1, 0x07, 0xAB, 0x01, 0xE0, + 0x0F, 0xE0, 0x28, 0xE0, 0x31, 0x46, 0x05, 0x9A, 0x07, 0x98, 0xFF, 0xF7, 0x7C, 0xFD, 0x01, 0x27, + 0x07, 0xE0, 0x33, 0x46, 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0xCD, 0xF8, 0x00, 0xB0, 0xFF, 0xF7, + 0x89, 0xFB, 0x01, 0x20, 0x5E, 0x99, 0xB0, 0x40, 0x01, 0x43, 0xE8, 0x4A, 0x5E, 0x91, 0x61, 0x99, + 0x11, 0x80, 0xE7, 0x4A, 0x60, 0x99, 0x11, 0x80, 0xE6, 0x49, 0x0A, 0x78, 0x32, 0xB1, 0x9D, 0xF8, + 0x72, 0x21, 0x04, 0x43, 0x01, 0x2A, 0x01, 0xD9, 0x81, 0xF8, 0x00, 0xB0, 0xBD, 0xF8, 0x40, 0x10, + 0xC9, 0x05, 0x00, 0xD5, 0x05, 0x43, 0x76, 0x1C, 0xF6, 0xB2, 0x9D, 0xF8, 0x72, 0x01, 0xB0, 0x42, + 0xBF, 0xF4, 0x09, 0xAF, 0xD8, 0x48, 0xDD, 0x4A, 0xDB, 0x4B, 0x41, 0x78, 0xA2, 0xF5, 0x66, 0x70, + 0x01, 0xF0, 0x0F, 0xFE, 0xDA, 0x48, 0x9D, 0xF8, 0x72, 0x11, 0x00, 0xF8, 0x05, 0x1F, 0xD9, 0x49, + 0x04, 0x83, 0x85, 0x83, 0xD8, 0x48, 0x81, 0xF8, 0x00, 0xA0, 0xD8, 0x49, 0x07, 0x70, 0xD8, 0x48, + 0x81, 0xF8, 0x00, 0x90, 0x02, 0x21, 0x02, 0xF0, 0x53, 0xFB, 0x04, 0x21, 0xD5, 0x48, 0x02, 0xF0, + 0x4F, 0xFB, 0xC9, 0x48, 0x01, 0x21, 0x18, 0x30, 0x02, 0xF0, 0xDF, 0xFB, 0xC6, 0x48, 0x01, 0x21, + 0x1C, 0x30, 0x02, 0xF0, 0xDA, 0xFB, 0xC4, 0x48, 0x01, 0x21, 0x24, 0x30, 0x02, 0xF0, 0xD5, 0xFB, + 0xC1, 0x48, 0x02, 0x21, 0x20, 0x30, 0x02, 0xF0, 0xD0, 0xFB, 0x65, 0xB0, 0x82, 0xE4, 0x2D, 0xE9, + 0xF0, 0x4F, 0xBF, 0x48, 0x00, 0x25, 0xE3, 0xB0, 0xB0, 0xF9, 0x00, 0x60, 0xBA, 0x48, 0xA9, 0x46, + 0xA8, 0x46, 0x01, 0x21, 0x1C, 0x30, 0x02, 0xF0, 0x5D, 0xFB, 0xB7, 0x48, 0x01, 0x21, 0x24, 0x30, + 0x02, 0xF0, 0x58, 0xFB, 0xB4, 0x48, 0x02, 0x21, 0x20, 0x30, 0x02, 0xF0, 0x53, 0xFB, 0x02, 0x21, + 0xBB, 0x48, 0x02, 0xF0, 0x05, 0xFB, 0x04, 0x21, 0xBA, 0x48, 0x02, 0xF0, 0x01, 0xFB, 0xDF, 0xF8, + 0xB8, 0xA2, 0x4F, 0xF4, 0x66, 0x77, 0x39, 0x46, 0x54, 0x46, 0xDA, 0xF8, 0x1C, 0x00, 0x0A, 0xF0, + 0x38, 0xFB, 0x39, 0x46, 0x60, 0x6A, 0x0A, 0xF0, 0x34, 0xFB, 0xB3, 0x48, 0xB0, 0xF9, 0x00, 0x00, + 0x41, 0x00, 0x20, 0x6A, 0x0A, 0xF0, 0x2D, 0xFB, 0x39, 0x46, 0xB0, 0x48, 0x0A, 0xF0, 0x29, 0xFB, + 0xAB, 0x46, 0xAF, 0x48, 0x84, 0xF8, 0x01, 0xB0, 0x8D, 0xF8, 0x72, 0xB1, 0x00, 0x68, 0x19, 0x90, + 0x5F, 0x46, 0x01, 0x23, 0x5A, 0x46, 0x19, 0xA9, 0xA0, 0x69, 0x00, 0xF0, 0x2D, 0xFB, 0x01, 0x24, + 0x05, 0x97, 0x8C, 0xE0, 0x19, 0xA8, 0x00, 0xEB, 0x84, 0x00, 0x5D, 0x90, 0x19, 0xAA, 0x21, 0x46, + 0x07, 0xA8, 0x05, 0x9B, 0xFF, 0xF7, 0x63, 0xFB, 0x07, 0xAB, 0x21, 0x46, 0x5D, 0x9A, 0x07, 0x98, + 0xFF, 0xF7, 0x85, 0xFB, 0x01, 0x27, 0x23, 0x46, 0x05, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0x00, 0x97, + 0xFF, 0xF7, 0xD0, 0xFA, 0x0D, 0xF1, 0x5A, 0x00, 0x00, 0xF0, 0x36, 0xF9, 0x28, 0xB1, 0xBD, 0xF8, + 0x40, 0x00, 0x40, 0xF0, 0x01, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0x5D, 0x98, 0x00, 0xF0, 0x3E, 0xF9, + 0x28, 0xB1, 0xBD, 0xF8, 0x40, 0x00, 0x40, 0xF0, 0x08, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0xBD, 0xF9, + 0x4E, 0x00, 0xB0, 0x42, 0x55, 0xDD, 0x07, 0xFA, 0x04, 0xF0, 0x05, 0x99, 0x03, 0x90, 0x08, 0x42, + 0x39, 0xD1, 0xBD, 0xF8, 0x40, 0x00, 0x10, 0xF4, 0xC0, 0x7F, 0x34, 0xD1, 0x7C, 0x48, 0x05, 0xAA, + 0x07, 0xA9, 0xB0, 0xF9, 0x00, 0x00, 0x8D, 0xE8, 0x07, 0x00, 0x22, 0x46, 0x5D, 0x9B, 0xDA, 0xF8, + 0x18, 0x10, 0xDA, 0xF8, 0x24, 0x00, 0xFF, 0xF7, 0xEF, 0xFB, 0x5F, 0x90, 0x05, 0x99, 0x03, 0x98, + 0x08, 0x42, 0x1E, 0xD0, 0x7F, 0x48, 0xBD, 0xF8, 0x42, 0x10, 0x00, 0x68, 0x90, 0xF8, 0x0E, 0x23, + 0x91, 0x42, 0x05, 0xD8, 0x90, 0xF8, 0xE0, 0x02, 0x81, 0x07, 0x12, 0xD4, 0x40, 0x07, 0x10, 0xD4, + 0x07, 0xA9, 0x19, 0xAA, 0x05, 0xA8, 0xCD, 0xE9, 0x00, 0x21, 0xCD, 0xE9, 0x02, 0x07, 0x0D, 0xF1, + 0x56, 0x03, 0x22, 0x46, 0xDA, 0xF8, 0x24, 0x10, 0xDA, 0xF8, 0x18, 0x00, 0xFF, 0xF7, 0xF2, 0xFB, + 0xD8, 0xB9, 0x5F, 0x98, 0x68, 0xB9, 0xBD, 0xF8, 0x42, 0x00, 0x07, 0xA9, 0xFF, 0xF7, 0x43, 0xFC, + 0x38, 0xB1, 0x07, 0xAB, 0x21, 0x46, 0x5D, 0x9A, 0x07, 0x98, 0xFF, 0xF7, 0x54, 0xFC, 0x01, 0x25, + 0x07, 0xE0, 0x23, 0x46, 0x05, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0xCD, 0xF8, 0x00, 0xB0, 0xFF, 0xF7, + 0x61, 0xFA, 0x05, 0x98, 0xA7, 0x40, 0x07, 0x43, 0x05, 0x97, 0x64, 0x1C, 0xE4, 0xB2, 0x9D, 0xF8, + 0x72, 0x01, 0xA0, 0x42, 0xBF, 0xF4, 0x6E, 0xAF, 0x53, 0x4B, 0x54, 0x4A, 0x9A, 0xF8, 0x01, 0x10, + 0x5A, 0x48, 0x01, 0xF0, 0xFE, 0xFC, 0x52, 0x49, 0x9D, 0xF8, 0x72, 0x01, 0x48, 0x71, 0x51, 0x49, + 0x51, 0x48, 0x81, 0xF8, 0x00, 0x90, 0x51, 0x49, 0x05, 0x70, 0x51, 0x48, 0x81, 0xF8, 0x00, 0x80, + 0x02, 0x21, 0x02, 0xF0, 0x45, 0xFA, 0x04, 0x21, 0x4E, 0x48, 0x02, 0xF0, 0x41, 0xFA, 0x42, 0x48, + 0x01, 0x21, 0x18, 0x30, 0x02, 0xF0, 0xD1, 0xFA, 0x3F, 0x48, 0x01, 0x21, 0x1C, 0x30, 0x02, 0xF0, + 0xCC, 0xFA, 0x3D, 0x48, 0x01, 0x21, 0x24, 0x30, 0x02, 0xF0, 0xC7, 0xFA, 0x3A, 0x48, 0x02, 0x21, + 0x20, 0x30, 0x02, 0xF0, 0xC2, 0xFA, 0x63, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x3D, 0x49, 0x00, 0x20, + 0x08, 0x70, 0x3D, 0x49, 0x08, 0x70, 0x3D, 0x49, 0x08, 0x70, 0x36, 0x49, 0x08, 0x70, 0xA8, 0x21, + 0x35, 0x48, 0x0A, 0xF0, 0x68, 0xBA, 0xF1, 0xE7, 0x2F, 0x49, 0x00, 0x20, 0x38, 0x4A, 0x08, 0x62, + 0x88, 0x61, 0xC8, 0x61, 0x10, 0x60, 0x37, 0x4A, 0x10, 0x60, 0x32, 0x4A, 0x10, 0x70, 0x32, 0x4A, + 0x10, 0x70, 0x32, 0x4A, 0x10, 0x70, 0x2B, 0x4A, 0x10, 0x70, 0x48, 0x70, 0x70, 0x47, 0x26, 0x49, + 0x10, 0xB5, 0x00, 0x20, 0x48, 0x70, 0x4F, 0xF4, 0x66, 0x71, 0x30, 0x48, 0x0A, 0xF0, 0x29, 0xFA, + 0x25, 0x48, 0xA8, 0x21, 0xA8, 0x38, 0x0A, 0xF0, 0x46, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0xA8, 0x21, + 0x21, 0x48, 0x0A, 0xF0, 0x40, 0xBA, 0x2D, 0xE9, 0xF7, 0x4F, 0x1B, 0x48, 0x0D, 0x46, 0x41, 0x78, + 0x0F, 0x29, 0x01, 0xD2, 0x49, 0x1C, 0x41, 0x70, 0x01, 0xF0, 0xFF, 0x09, 0x1B, 0x49, 0x82, 0xF8, + 0x41, 0x90, 0x01, 0xEB, 0x89, 0x00, 0x29, 0x68, 0x01, 0x60, 0xA9, 0x78, 0x1F, 0x48, 0x0A, 0xF0, + 0x1F, 0xFB, 0x82, 0x46, 0xA8, 0x78, 0x19, 0xE0, 0x00, 0x98, 0x2C, 0x78, 0x00, 0xEB, 0xC8, 0x0B, + 0x0D, 0xE0, 0xDB, 0xE9, 0x00, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0x43, 0xF9, + 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x01, 0xD0, 0x0A, 0xF8, 0x04, 0x90, 0x64, 0x1C, 0x68, 0x78, + 0xA0, 0x42, 0xEE, 0xDA, 0x0A, 0xF1, 0x28, 0x0A, 0x08, 0xF1, 0x01, 0x00, 0xE9, 0x78, 0x80, 0x46, + 0x41, 0x45, 0xE1, 0xDA, 0xBD, 0xE8, 0xFE, 0x8F, 0x14, 0x06, 0x10, 0x00, 0x70, 0x06, 0x10, 0x00, + 0x6E, 0x06, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x48, 0x3F, 0x10, 0x00, 0x4C, 0x1C, 0x01, 0x20, + 0xE6, 0x43, 0x01, 0x20, 0xC2, 0x06, 0x10, 0x00, 0xC3, 0x06, 0x10, 0x00, 0xC4, 0x06, 0x10, 0x00, + 0x3C, 0x06, 0x10, 0x00, 0x48, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0xB4, 0x18, 0x01, 0x20, + 0x64, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x01, 0x78, 0x59, 0xB1, 0x95, 0x4A, 0x12, 0x78, + 0x52, 0x1E, 0x91, 0x42, 0x06, 0xD0, 0x40, 0x78, 0x20, 0xB1, 0x93, 0x49, 0x09, 0x78, 0x49, 0x1E, + 0x88, 0x42, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x78, 0x29, 0xB1, + 0x8C, 0x49, 0x42, 0x78, 0x09, 0x78, 0x49, 0x1E, 0x8A, 0x42, 0x09, 0xD1, 0x81, 0x78, 0x29, 0xB1, + 0xC1, 0x78, 0x89, 0x48, 0x00, 0x78, 0x40, 0x1E, 0x81, 0x42, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x47, + 0x00, 0x20, 0x70, 0x47, 0xF0, 0xB5, 0x85, 0x4D, 0x00, 0x22, 0x05, 0xEB, 0xC2, 0x06, 0x00, 0x23, + 0xC6, 0xE9, 0x00, 0x33, 0x52, 0x1C, 0xD2, 0xB2, 0x17, 0x2A, 0xF6, 0xD3, 0x8A, 0x78, 0x2C, 0xE0, + 0x00, 0xEB, 0xC2, 0x03, 0xD3, 0xE9, 0x00, 0x76, 0x57, 0xEA, 0x06, 0x03, 0x23, 0xD0, 0x74, 0x08, + 0x4F, 0xEA, 0x37, 0x03, 0x17, 0xEB, 0x07, 0x0E, 0x46, 0xEB, 0x06, 0x0C, 0x44, 0xEA, 0x0C, 0x04, + 0x34, 0x43, 0x43, 0xEA, 0x0E, 0x03, 0x05, 0xEB, 0xC2, 0x06, 0x3B, 0x43, 0xD6, 0xE9, 0x00, 0x7C, + 0x1F, 0x43, 0x4C, 0xEA, 0x04, 0x0C, 0xC6, 0xE9, 0x00, 0x7C, 0xD6, 0xE9, 0x02, 0x7C, 0x1F, 0x43, + 0x4C, 0xEA, 0x04, 0x0C, 0xC6, 0xE9, 0x02, 0x7C, 0xD6, 0xE9, 0x04, 0x7C, 0x1F, 0x43, 0x4C, 0xEA, + 0x04, 0x0C, 0xC6, 0xE9, 0x04, 0x7C, 0x52, 0x1C, 0xD2, 0xB2, 0xCB, 0x78, 0x93, 0x42, 0xCF, 0xD2, + 0x00, 0x22, 0x65, 0x4B, 0x0A, 0xE0, 0x00, 0xBF, 0x05, 0xEB, 0xC2, 0x04, 0x00, 0xEB, 0xC2, 0x07, + 0xD4, 0xE9, 0x02, 0x64, 0xC7, 0xE9, 0x00, 0x64, 0x52, 0x1C, 0xD2, 0xB2, 0x1C, 0x78, 0xA2, 0x42, + 0xF2, 0xD3, 0x08, 0x78, 0x08, 0xB1, 0x40, 0x1E, 0x08, 0x70, 0x5A, 0x4A, 0x48, 0x78, 0x12, 0x78, + 0x52, 0x1E, 0x90, 0x42, 0x01, 0xDA, 0x40, 0x1C, 0x48, 0x70, 0x88, 0x78, 0x08, 0xB1, 0x40, 0x1E, + 0x88, 0x70, 0x1A, 0x78, 0xC8, 0x78, 0x52, 0x1E, 0x90, 0x42, 0x01, 0xDA, 0x40, 0x1C, 0xC8, 0x70, + 0xF0, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x94, 0x78, 0x16, 0x46, 0x04, 0xEB, 0x84, 0x02, 0x8B, 0x46, + 0x00, 0xEB, 0xC2, 0x00, 0x00, 0x21, 0x00, 0xF1, 0x29, 0x08, 0x20, 0xE0, 0x00, 0x20, 0x81, 0x46, + 0x82, 0x46, 0x35, 0x78, 0x77, 0x78, 0x0F, 0xE0, 0x18, 0xF8, 0x05, 0x20, 0x5A, 0x45, 0x09, 0xD1, + 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0x66, 0xF8, 0x41, 0xEA, 0x0A, 0x0A, 0x40, 0xEA, + 0x09, 0x09, 0x01, 0x21, 0x6D, 0x1C, 0xED, 0xB2, 0xAF, 0x42, 0xED, 0xD2, 0x03, 0x9B, 0x08, 0xF1, + 0x28, 0x08, 0x03, 0xEB, 0xC4, 0x03, 0x64, 0x1C, 0xC3, 0xE9, 0x00, 0x9A, 0xE4, 0xB2, 0xF0, 0x78, + 0xA0, 0x42, 0xDB, 0xD2, 0x04, 0xB0, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x0A, 0x78, 0x43, 0x78, + 0x9A, 0x42, 0x0B, 0xD8, 0x4A, 0x78, 0x03, 0x78, 0x9A, 0x42, 0x07, 0xD3, 0x8A, 0x78, 0xC3, 0x78, + 0x9A, 0x42, 0x03, 0xD8, 0xC9, 0x78, 0x80, 0x78, 0x81, 0x42, 0x01, 0xD2, 0x00, 0x20, 0x70, 0x47, + 0x01, 0x20, 0x70, 0x47, 0x70, 0xB5, 0x0C, 0x78, 0x8B, 0x78, 0x4D, 0x78, 0xC9, 0x78, 0x9A, 0xB1, + 0x0C, 0xB1, 0x64, 0x1E, 0xE4, 0xB2, 0x27, 0x4A, 0x12, 0x78, 0x52, 0x1E, 0x95, 0x42, 0x01, 0xDA, + 0x6D, 0x1C, 0xED, 0xB2, 0x0B, 0xB1, 0x5B, 0x1E, 0xDB, 0xB2, 0x23, 0x4A, 0x12, 0x78, 0x52, 0x1E, + 0x91, 0x42, 0x01, 0xDA, 0x49, 0x1C, 0xC9, 0xB2, 0x03, 0xEB, 0x83, 0x02, 0x00, 0xEB, 0xC2, 0x02, + 0x00, 0x26, 0x29, 0x32, 0x09, 0xE0, 0x20, 0x46, 0x02, 0xE0, 0x16, 0x54, 0x40, 0x1C, 0xC0, 0xB2, + 0xA8, 0x42, 0xFA, 0xD9, 0x5B, 0x1C, 0xDB, 0xB2, 0x28, 0x32, 0x8B, 0x42, 0xF3, 0xD9, 0x70, 0xBD, + 0x2D, 0xE9, 0xF0, 0x43, 0x9C, 0x78, 0x93, 0xF8, 0x03, 0xC0, 0x04, 0xEB, 0x84, 0x05, 0x00, 0xEB, + 0xC5, 0x05, 0x10, 0x48, 0x90, 0xF8, 0x00, 0x90, 0x04, 0xFB, 0x09, 0xF0, 0x01, 0xEB, 0x40, 0x06, + 0x00, 0x20, 0x29, 0x35, 0x12, 0xE0, 0x19, 0x78, 0x5F, 0x78, 0x08, 0xE0, 0x15, 0xF8, 0x01, 0x80, + 0x90, 0x45, 0x02, 0xD1, 0x36, 0xF9, 0x11, 0x80, 0x40, 0x44, 0x49, 0x1C, 0xC9, 0xB2, 0x8F, 0x42, + 0xF4, 0xD2, 0x64, 0x1C, 0x06, 0xEB, 0x49, 0x06, 0xE4, 0xB2, 0x28, 0x35, 0xA4, 0x45, 0xEA, 0xD2, + 0xBD, 0xE8, 0xF0, 0x83, 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xF0, 0x3F, 0x10, 0x00, + 0x2D, 0xE9, 0xF0, 0x47, 0x80, 0x46, 0x27, 0x48, 0x8C, 0x78, 0x0D, 0x46, 0x00, 0x78, 0x80, 0x1E, + 0x01, 0x2C, 0x05, 0xD9, 0xE9, 0x78, 0x81, 0x42, 0x02, 0xDA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, + 0x02, 0x2C, 0x01, 0xD2, 0x02, 0x27, 0x01, 0xE0, 0xEF, 0x78, 0xC4, 0xB2, 0x4F, 0xF0, 0x00, 0x09, + 0x21, 0x46, 0xD8, 0xF8, 0x08, 0x00, 0x0A, 0xF0, 0x83, 0xF9, 0x06, 0x46, 0x21, 0x46, 0xD8, 0xF8, + 0x04, 0x00, 0x0A, 0xF0, 0x7D, 0xF9, 0x01, 0x46, 0x17, 0x48, 0x02, 0x78, 0x15, 0xE0, 0x28, 0x78, + 0x6B, 0x78, 0x0A, 0xE0, 0x36, 0xF9, 0x10, 0xC0, 0x31, 0xF9, 0x10, 0x80, 0xC4, 0x45, 0x02, 0xD0, + 0x4F, 0xF0, 0x01, 0x09, 0x03, 0xE0, 0x40, 0x1C, 0xC0, 0xB2, 0x83, 0x42, 0xF2, 0xD2, 0x64, 0x1C, + 0x06, 0xEB, 0x42, 0x06, 0x01, 0xEB, 0x42, 0x01, 0xE4, 0xB2, 0xBC, 0x42, 0xE7, 0xD9, 0x48, 0x46, + 0xCC, 0xE7, 0x08, 0x49, 0x09, 0x78, 0x49, 0x1E, 0xCA, 0xB2, 0x90, 0xF8, 0x3F, 0x10, 0x09, 0xB1, + 0x91, 0x42, 0x05, 0xD1, 0x81, 0x8C, 0x41, 0xF0, 0x02, 0x01, 0x81, 0x84, 0x01, 0x20, 0x70, 0x47, + 0x00, 0x20, 0x70, 0x47, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x30, 0xB5, 0xB0, 0xB1, + 0x88, 0x42, 0x14, 0xD0, 0x02, 0xD2, 0x0A, 0x46, 0x01, 0x46, 0x10, 0x46, 0xC9, 0x4A, 0x53, 0x68, + 0x03, 0xEB, 0x40, 0x03, 0x1C, 0x78, 0x8C, 0x42, 0x09, 0xD0, 0x5C, 0x78, 0x8C, 0x42, 0x06, 0xD0, + 0x95, 0x68, 0x2A, 0x5C, 0x02, 0x2A, 0x02, 0xD2, 0x54, 0x1C, 0x2C, 0x54, 0x99, 0x54, 0x08, 0x46, + 0x30, 0xBD, 0xF0, 0xB5, 0x03, 0xEB, 0x82, 0x04, 0xA5, 0x78, 0x05, 0xEB, 0x85, 0x06, 0x00, 0xEB, + 0xC6, 0x06, 0xE0, 0x78, 0x28, 0x36, 0xA8, 0x42, 0x0F, 0xD3, 0x20, 0x78, 0x07, 0xE0, 0x37, 0x18, + 0x97, 0xF8, 0x01, 0xC0, 0x94, 0x45, 0x00, 0xD1, 0x79, 0x70, 0x40, 0x1C, 0xC0, 0xB2, 0x67, 0x78, + 0x87, 0x42, 0xF4, 0xD2, 0x6D, 0x1C, 0xED, 0xB2, 0xEB, 0xE7, 0x03, 0xEB, 0x81, 0x00, 0x25, 0x68, + 0x05, 0x60, 0x03, 0xEB, 0x42, 0x00, 0x03, 0xEB, 0x41, 0x01, 0x30, 0xF8, 0xB4, 0x2F, 0xA1, 0xF8, + 0xB4, 0x20, 0xAD, 0x49, 0x09, 0x68, 0x21, 0x60, 0x00, 0x21, 0x01, 0x80, 0x93, 0xF8, 0x0E, 0x01, + 0x40, 0x1E, 0x83, 0xF8, 0x0E, 0x01, 0xF0, 0xBD, 0x2D, 0xE9, 0xFF, 0x4F, 0x88, 0x46, 0x08, 0x46, + 0x09, 0x78, 0x8F, 0xB0, 0xFF, 0x29, 0x13, 0xD0, 0x8A, 0x46, 0xA4, 0x49, 0x42, 0x78, 0x09, 0x78, + 0x8A, 0x42, 0x00, 0xD2, 0x51, 0x1C, 0xCE, 0xB2, 0xA1, 0x49, 0x90, 0xF8, 0x02, 0x90, 0xC0, 0x78, + 0x09, 0x78, 0x88, 0x42, 0x01, 0xD2, 0x40, 0x1C, 0x00, 0xE0, 0x08, 0x46, 0xC7, 0xB2, 0x04, 0xE0, + 0x4F, 0xF0, 0x00, 0x0A, 0x56, 0x46, 0xD1, 0x46, 0x57, 0x46, 0x11, 0x98, 0x4F, 0xF0, 0x00, 0x0B, + 0x08, 0xB1, 0x98, 0xF8, 0x0E, 0xB1, 0x93, 0x4A, 0x11, 0x68, 0x01, 0xF1, 0x5A, 0x00, 0xC2, 0xE9, + 0x01, 0x10, 0x02, 0x46, 0x5F, 0xF0, 0x2C, 0x00, 0x00, 0x23, 0x01, 0xF8, 0x10, 0x00, 0x13, 0x54, + 0x40, 0x1E, 0xC0, 0xB2, 0xF8, 0xD2, 0x0B, 0xF1, 0x01, 0x00, 0x0D, 0x90, 0xC0, 0xB2, 0x06, 0x90, + 0x0F, 0x98, 0x09, 0xEB, 0x89, 0x01, 0x00, 0xEB, 0xC1, 0x05, 0x09, 0xF1, 0x01, 0x00, 0x09, 0x95, + 0x39, 0xE0, 0x00, 0xBF, 0x0A, 0xF1, 0x01, 0x00, 0x0A, 0x95, 0xC4, 0xB2, 0x28, 0x35, 0x2E, 0xE0, + 0x29, 0x19, 0x08, 0x68, 0xE0, 0xB1, 0x28, 0x5D, 0x38, 0xB3, 0x11, 0xF8, 0x01, 0x1C, 0x00, 0x20, + 0x01, 0xB1, 0x08, 0x46, 0x0A, 0x99, 0x09, 0x5D, 0x09, 0xB1, 0xFF, 0xF7, 0x57, 0xFF, 0x12, 0x99, + 0x61, 0xB1, 0x0A, 0x99, 0x21, 0x44, 0x0E, 0x91, 0x11, 0xF8, 0x01, 0x1C, 0x09, 0xB1, 0xFF, 0xF7, + 0x4D, 0xFF, 0x0E, 0x99, 0x49, 0x78, 0x09, 0xB1, 0xFF, 0xF7, 0x48, 0xFF, 0x18, 0xB1, 0x0B, 0xE0, + 0xE4, 0x1C, 0xE4, 0xB2, 0x09, 0xE0, 0x06, 0x98, 0x2D, 0x28, 0x03, 0xD2, 0x41, 0x1C, 0xC9, 0xB2, + 0x06, 0x91, 0x01, 0xE0, 0x40, 0x1E, 0xC0, 0xB2, 0x28, 0x55, 0x64, 0x1C, 0xE4, 0xB2, 0xB4, 0x42, + 0xCE, 0xD9, 0x07, 0x98, 0x40, 0x1C, 0xC0, 0xB2, 0x07, 0x90, 0xB8, 0x42, 0xC2, 0xD9, 0x06, 0x98, + 0x00, 0xF0, 0x6F, 0xF8, 0x06, 0x90, 0x0D, 0x98, 0x00, 0x22, 0xC0, 0xB2, 0x62, 0x4C, 0x09, 0xE0, + 0x08, 0xEB, 0x80, 0x03, 0x21, 0x68, 0x19, 0x60, 0x08, 0xEB, 0x40, 0x01, 0x40, 0x1C, 0xA1, 0xF8, + 0xB4, 0x20, 0xC0, 0xB2, 0x06, 0x99, 0x88, 0x42, 0xF2, 0xD3, 0x09, 0x98, 0x4D, 0x46, 0x28, 0x30, + 0x00, 0x90, 0x39, 0xE0, 0x54, 0x46, 0x30, 0xE0, 0x20, 0x44, 0x01, 0x21, 0x09, 0x58, 0xE9, 0xB3, + 0x41, 0x78, 0x41, 0xB3, 0x53, 0x4A, 0x52, 0x68, 0x12, 0xF8, 0x11, 0x10, 0x41, 0x70, 0x08, 0xEB, + 0x41, 0x00, 0x08, 0xEB, 0x81, 0x09, 0x30, 0xF8, 0xB4, 0x2F, 0x52, 0x1C, 0x02, 0x80, 0x99, 0xF8, + 0x00, 0x10, 0x20, 0x46, 0x04, 0xF0, 0xE6, 0xFB, 0x89, 0xF8, 0x00, 0x00, 0x99, 0xF8, 0x01, 0x10, + 0x20, 0x46, 0x04, 0xF0, 0xE3, 0xFB, 0x89, 0xF8, 0x01, 0x00, 0x99, 0xF8, 0x02, 0x10, 0x28, 0x46, + 0x04, 0xF0, 0xD8, 0xFB, 0x89, 0xF8, 0x02, 0x00, 0x99, 0xF8, 0x03, 0x10, 0x28, 0x46, 0x04, 0xF0, + 0xD5, 0xFB, 0x89, 0xF8, 0x03, 0x00, 0x64, 0x1C, 0xE4, 0xB2, 0x00, 0x98, 0xB4, 0x42, 0xCB, 0xD3, + 0x28, 0x30, 0x6D, 0x1C, 0xED, 0xB2, 0x00, 0x90, 0xBD, 0x42, 0xC3, 0xD3, 0x06, 0x98, 0x40, 0x1E, + 0xC2, 0xB2, 0x88, 0xF8, 0x0E, 0x21, 0x11, 0x98, 0x00, 0x28, 0x00, 0xE0, 0x0B, 0xE0, 0x0D, 0xD0, + 0xA2, 0xEB, 0x0B, 0x00, 0x01, 0x28, 0x09, 0xD1, 0x11, 0x99, 0x0F, 0x98, 0x13, 0xB0, 0x43, 0x46, + 0xBD, 0xE8, 0xF0, 0x4F, 0xDD, 0xE6, 0xE4, 0x1C, 0xE4, 0xB2, 0xDC, 0xE7, 0x13, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0x2D, 0xE9, 0xF0, 0x5F, 0x07, 0x46, 0x00, 0x25, 0xDF, 0xF8, 0xA8, 0xB0, 0x2C, 0xE0, + 0xDB, 0xF8, 0x08, 0x10, 0x4E, 0x5D, 0xDB, 0xF8, 0x04, 0x10, 0x01, 0xEB, 0x45, 0x0A, 0x1A, 0xE0, + 0x0A, 0xEB, 0x06, 0x00, 0x80, 0x46, 0x10, 0xF8, 0x01, 0x1C, 0x10, 0xF8, 0x02, 0x9C, 0x08, 0x46, + 0x00, 0xF0, 0x35, 0xF8, 0x04, 0x46, 0x48, 0x46, 0x00, 0xF0, 0x31, 0xF8, 0x84, 0x42, 0x02, 0xD2, + 0x01, 0x46, 0x20, 0x46, 0x0C, 0x46, 0xDB, 0xF8, 0x04, 0x10, 0x76, 0x1E, 0xF6, 0xB2, 0x01, 0xF8, + 0x10, 0x40, 0x08, 0xF8, 0x02, 0x4C, 0x01, 0x2E, 0xE2, 0xD8, 0x04, 0xD1, 0x28, 0x46, 0x00, 0xF0, + 0x1E, 0xF8, 0x8A, 0xF8, 0x00, 0x00, 0x6D, 0x1C, 0xED, 0xB2, 0xBD, 0x42, 0xD0, 0xD3, 0x00, 0x21, + 0x08, 0x46, 0xDB, 0xF8, 0x04, 0x40, 0x0D, 0xE0, 0x04, 0xEB, 0x40, 0x02, 0x13, 0x78, 0x83, 0x42, + 0x03, 0xD1, 0x11, 0x70, 0x49, 0x1C, 0xC9, 0xB2, 0x02, 0xE0, 0x14, 0xF8, 0x13, 0x30, 0x13, 0x70, + 0x40, 0x1C, 0xC0, 0xB2, 0xB8, 0x42, 0xEF, 0xD3, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x05, 0x4A, + 0xD2, 0xE9, 0x01, 0x12, 0x02, 0xE0, 0x00, 0xBF, 0x11, 0xF8, 0x10, 0x00, 0x13, 0x5C, 0x00, 0x2B, + 0xFA, 0xD1, 0x70, 0x47, 0x3C, 0x06, 0x10, 0x00, 0x52, 0x6C, 0x01, 0x00, 0xBA, 0x06, 0x10, 0x00, + 0xB9, 0x06, 0x10, 0x00, 0xF0, 0xB5, 0xB2, 0xF9, 0x00, 0x40, 0x06, 0x68, 0xB4, 0x42, 0x02, 0xDD, + 0xB3, 0xF9, 0x00, 0x10, 0x30, 0xE0, 0x02, 0xEB, 0x41, 0x04, 0x34, 0xF9, 0x02, 0x5C, 0xB5, 0x42, + 0x04, 0xDA, 0x03, 0xEB, 0x41, 0x01, 0x31, 0xF9, 0x02, 0x1C, 0x25, 0xE0, 0x00, 0x25, 0x2C, 0x46, + 0x4F, 0x1E, 0x0C, 0xE0, 0x32, 0xF9, 0x14, 0xC0, 0xB4, 0x45, 0x07, 0xDC, 0x02, 0xEB, 0x44, 0x0C, + 0xBC, 0xF9, 0x02, 0xC0, 0xB4, 0x45, 0x01, 0xDB, 0x25, 0x46, 0x0C, 0x46, 0x64, 0x1C, 0xBC, 0x42, + 0xF0, 0xDB, 0x32, 0xF9, 0x15, 0x40, 0x03, 0xEB, 0x45, 0x01, 0x33, 0xF9, 0x15, 0x30, 0xB1, 0xF9, + 0x02, 0x10, 0x02, 0xEB, 0x45, 0x02, 0x36, 0x1B, 0xC9, 0x1A, 0xB2, 0xF9, 0x02, 0x20, 0x71, 0x43, + 0x12, 0x1B, 0x91, 0xFB, 0xF2, 0xF1, 0x19, 0x44, 0x01, 0x60, 0xF0, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, + 0x05, 0x46, 0x1E, 0x48, 0x00, 0x68, 0x00, 0xF2, 0x0F, 0x53, 0x11, 0xB3, 0x03, 0x29, 0x27, 0xD0, + 0x04, 0x29, 0x30, 0xD1, 0x90, 0xF8, 0x08, 0x15, 0x90, 0xF8, 0x09, 0x45, 0x90, 0xF8, 0x0E, 0x05, + 0x03, 0xEB, 0x41, 0x06, 0x03, 0xEB, 0x40, 0x0C, 0x50, 0x18, 0x20, 0x44, 0x0C, 0xEB, 0x41, 0x07, + 0x64, 0x28, 0x20, 0xDC, 0x01, 0x29, 0x03, 0xDD, 0x28, 0x1D, 0x62, 0x46, 0xFF, 0xF7, 0xA2, 0xFF, + 0x01, 0x2C, 0x18, 0xDD, 0x28, 0x46, 0x33, 0x46, 0x3A, 0x46, 0x21, 0x46, 0xBD, 0xE8, 0xF0, 0x41, + 0x98, 0xE7, 0x90, 0xF8, 0x08, 0x15, 0x90, 0xF8, 0x09, 0x45, 0x90, 0xF8, 0x0A, 0x25, 0x05, 0xE0, + 0x90, 0xF8, 0x08, 0x15, 0x90, 0xF8, 0x09, 0x45, 0x90, 0xF8, 0x0D, 0x25, 0x03, 0xEB, 0x41, 0x06, + 0x03, 0xEB, 0x42, 0x0C, 0xD8, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x30, 0xB5, 0x42, 0x78, 0x03, 0x78, 0xCD, 0x8C, 0xD2, 0x1A, 0xC3, 0x78, 0x80, 0x78, 0x52, 0x1C, + 0x1B, 0x1A, 0x5B, 0x1C, 0x05, 0xFB, 0x02, 0xF0, 0xD4, 0x18, 0x5D, 0x43, 0x40, 0x00, 0x6A, 0x00, + 0xB0, 0xFB, 0xF4, 0xF0, 0xB2, 0xFB, 0xF4, 0xF2, 0x90, 0x42, 0x02, 0xD9, 0xC8, 0x85, 0x0A, 0x86, + 0x30, 0xBD, 0xCA, 0x85, 0x08, 0x86, 0x30, 0xBD, 0x2D, 0xE9, 0xFF, 0x4F, 0x00, 0x27, 0x83, 0xB0, + 0x15, 0x46, 0x01, 0x97, 0x00, 0x97, 0x3E, 0x46, 0x3C, 0x46, 0xBB, 0x46, 0x91, 0x78, 0x09, 0xF0, + 0xF9, 0xFE, 0x82, 0x46, 0xAB, 0x78, 0x95, 0xF8, 0x03, 0x90, 0x28, 0xE0, 0x29, 0x78, 0x95, 0xF8, + 0x01, 0xC0, 0x8E, 0x46, 0x1D, 0xE0, 0x00, 0xBF, 0x1A, 0xF8, 0x01, 0x20, 0x04, 0x98, 0x82, 0x42, + 0x15, 0xD1, 0xA1, 0xEB, 0x0E, 0x02, 0x52, 0x1C, 0xDD, 0xF8, 0x00, 0x80, 0xA9, 0xEB, 0x03, 0x00, + 0x02, 0xFB, 0x02, 0x88, 0x40, 0x1C, 0xCD, 0xF8, 0x00, 0x80, 0xDD, 0xF8, 0x04, 0x80, 0x16, 0x44, + 0x02, 0xFB, 0x00, 0x82, 0x00, 0xFB, 0x00, 0xBB, 0x04, 0x44, 0x7F, 0x1C, 0x01, 0x92, 0x49, 0x1C, + 0xC9, 0xB2, 0x8C, 0x45, 0xE0, 0xD2, 0x5B, 0x1C, 0x0A, 0xF1, 0x28, 0x0A, 0xDB, 0xB2, 0x99, 0x45, + 0xD4, 0xD2, 0x4F, 0xF4, 0x7A, 0x70, 0x70, 0x43, 0x90, 0xFB, 0xF7, 0xF1, 0x4F, 0xF4, 0x7A, 0x70, + 0x60, 0x43, 0x90, 0xFB, 0xF7, 0xF3, 0x4F, 0xF4, 0x7A, 0x72, 0x01, 0xFB, 0x04, 0xF0, 0x71, 0x43, + 0x90, 0xFB, 0xF2, 0xF7, 0x91, 0xFB, 0xF2, 0xF6, 0x63, 0x43, 0x93, 0xFB, 0xF2, 0xF3, 0x01, 0x98, + 0x00, 0x99, 0xC0, 0x1B, 0x89, 0x1B, 0xAB, 0xEB, 0x03, 0x02, 0x06, 0x9C, 0x8B, 0x1A, 0x00, 0xD5, + 0x5B, 0x42, 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x03, 0xEB, 0x40, 0x00, 0x11, 0x44, 0x0A, 0x18, + 0x08, 0x1A, 0x52, 0x10, 0x40, 0x10, 0x4F, 0xF4, 0x7A, 0x71, 0x48, 0x43, 0x90, 0xFB, 0xF2, 0xF0, + 0xC0, 0xF5, 0x7A, 0x70, 0xA0, 0x85, 0x06, 0x99, 0x07, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x4F, + 0x6E, 0xE7, 0x00, 0x00, 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x25, 0xDD, 0xF8, 0x38, 0x80, 0x8B, 0x46, + 0x99, 0x46, 0x14, 0x46, 0x2E, 0x46, 0x2F, 0x46, 0x41, 0x46, 0x00, 0x98, 0x09, 0xF0, 0x88, 0xFE, + 0x30, 0xF9, 0x19, 0x00, 0xA0, 0x42, 0x32, 0xDD, 0xA8, 0xF1, 0x01, 0x00, 0x44, 0xB2, 0x08, 0xF1, + 0x01, 0x08, 0x28, 0xE0, 0x00, 0x2C, 0x22, 0xDB, 0xA9, 0x48, 0x00, 0x78, 0x84, 0x42, 0x1E, 0xDA, + 0xE1, 0xB2, 0x00, 0x98, 0x09, 0xF0, 0x74, 0xFE, 0xA6, 0x49, 0x82, 0x46, 0xA9, 0xF1, 0x01, 0x00, + 0x0A, 0x78, 0x40, 0xB2, 0x09, 0xF1, 0x01, 0x01, 0x0E, 0xE0, 0x00, 0x28, 0x08, 0xDB, 0x90, 0x42, + 0x06, 0xDA, 0x3B, 0xF9, 0x15, 0x30, 0x3A, 0xF9, 0x10, 0xC0, 0x1F, 0x44, 0x0C, 0xFB, 0x03, 0x66, + 0x6D, 0x1C, 0x40, 0x1C, 0xED, 0xB2, 0x40, 0xB2, 0x88, 0x42, 0xEE, 0xDD, 0x01, 0xE0, 0xED, 0x1C, + 0xED, 0xB2, 0x64, 0x1C, 0x64, 0xB2, 0x44, 0x45, 0xD4, 0xDD, 0x0F, 0xB1, 0x01, 0xE0, 0x06, 0x46, + 0x01, 0x27, 0x96, 0xFB, 0xF7, 0xF0, 0x04, 0xB0, 0x00, 0xB2, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, + 0xFF, 0x4F, 0x83, 0xB0, 0x91, 0x46, 0x10, 0x99, 0x08, 0x78, 0x00, 0xB1, 0x40, 0x1E, 0xC4, 0xB2, + 0x88, 0x78, 0x00, 0xB1, 0x40, 0x1E, 0xDF, 0xF8, 0x2C, 0xA2, 0xC5, 0xB2, 0x4A, 0x78, 0x9A, 0xF8, + 0x00, 0x00, 0x43, 0x1E, 0x9A, 0x42, 0x01, 0xDA, 0x50, 0x1C, 0x00, 0xE0, 0x40, 0x1E, 0xDF, 0xF8, + 0x10, 0xB2, 0xC6, 0xB2, 0xC9, 0x78, 0x9B, 0xF8, 0x00, 0x00, 0x42, 0x1E, 0x91, 0x42, 0x01, 0xDA, + 0x48, 0x1C, 0x00, 0xE0, 0x40, 0x1E, 0xC7, 0xB2, 0xCC, 0xB9, 0xA8, 0x46, 0x12, 0xE0, 0x01, 0x46, + 0x03, 0x98, 0x09, 0xF0, 0x2B, 0xFE, 0xCD, 0xE9, 0x00, 0x80, 0x23, 0x46, 0x49, 0x46, 0x06, 0x9A, + 0x04, 0x98, 0xFF, 0xF7, 0x7F, 0xFF, 0x01, 0x99, 0x21, 0xF8, 0x14, 0x00, 0x08, 0xF1, 0x01, 0x00, + 0x00, 0xF0, 0xFF, 0x08, 0x40, 0x46, 0xB8, 0x45, 0xE9, 0xD9, 0x64, 0x1C, 0xE4, 0xB2, 0x71, 0x48, + 0x00, 0x78, 0x40, 0x1E, 0x86, 0x42, 0x19, 0xD1, 0xA8, 0x46, 0x12, 0xE0, 0x01, 0x46, 0x03, 0x98, + 0x09, 0xF0, 0x0C, 0xFE, 0x82, 0x46, 0x33, 0x46, 0xCD, 0xF8, 0x00, 0x80, 0x49, 0x46, 0x06, 0x9A, + 0x04, 0x98, 0xFF, 0xF7, 0x5F, 0xFF, 0x2A, 0xF8, 0x16, 0x00, 0x08, 0xF1, 0x01, 0x00, 0x00, 0xF0, + 0xFF, 0x08, 0x40, 0x46, 0xB8, 0x45, 0xE9, 0xD9, 0x76, 0x1E, 0xF6, 0xB2, 0xC5, 0xB9, 0x29, 0x46, + 0x03, 0x98, 0x09, 0xF0, 0xF3, 0xFD, 0x82, 0x46, 0xA0, 0x46, 0x0C, 0xE0, 0x03, 0x46, 0x00, 0x95, + 0x49, 0x46, 0x06, 0x9A, 0x04, 0x98, 0xFF, 0xF7, 0x45, 0xFF, 0x2A, 0xF8, 0x18, 0x00, 0x08, 0xF1, + 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x08, 0x40, 0x46, 0xB0, 0x45, 0xEF, 0xD9, 0x6D, 0x1C, 0xED, 0xB2, + 0x9B, 0xF8, 0x00, 0x00, 0x40, 0x1E, 0x87, 0x42, 0x18, 0xD1, 0x39, 0x46, 0x03, 0x98, 0x09, 0xF0, + 0xD5, 0xFD, 0x82, 0x46, 0xA0, 0x46, 0x0C, 0xE0, 0x03, 0x46, 0x00, 0x97, 0x49, 0x46, 0x06, 0x9A, + 0x04, 0x98, 0xFF, 0xF7, 0x27, 0xFF, 0x2A, 0xF8, 0x18, 0x00, 0x08, 0xF1, 0x01, 0x00, 0x00, 0xF0, + 0xFF, 0x08, 0x40, 0x46, 0xB0, 0x45, 0xEF, 0xD9, 0x7F, 0x1E, 0xFF, 0xB2, 0xB9, 0xF9, 0x12, 0x00, + 0x5F, 0xEA, 0x00, 0x0A, 0x65, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0x62, 0xE0, 0x29, 0x46, 0x03, 0x98, + 0x09, 0xF0, 0xB4, 0xFD, 0x01, 0x90, 0x68, 0x1E, 0xC1, 0xB2, 0x04, 0x98, 0x09, 0xF0, 0xA0, 0xFD, + 0x00, 0x90, 0x29, 0x46, 0x04, 0x98, 0x09, 0xF0, 0x9B, 0xFD, 0x21, 0x46, 0x4D, 0xE0, 0x00, 0xBF, + 0x30, 0xF9, 0x11, 0x20, 0x06, 0x9B, 0x9A, 0x42, 0x42, 0xDD, 0x00, 0x9A, 0xB9, 0xF9, 0x00, 0x80, + 0x02, 0xEB, 0x41, 0x02, 0x00, 0x23, 0x32, 0xF9, 0x02, 0xCD, 0x0C, 0xFB, 0x08, 0x33, 0xB2, 0xF9, + 0x02, 0xC0, 0xB9, 0xF9, 0x02, 0x80, 0x0C, 0xFB, 0x08, 0x33, 0xB2, 0xF9, 0x04, 0xC0, 0xB9, 0xF9, + 0x04, 0x80, 0x0C, 0xFB, 0x08, 0x3B, 0x2B, 0x4B, 0xB9, 0xF9, 0x06, 0x80, 0x93, 0xF8, 0x00, 0xE0, + 0x02, 0xEB, 0x4E, 0x02, 0xB2, 0xF9, 0x00, 0xC0, 0x0C, 0xFB, 0x08, 0xB3, 0xB2, 0xF9, 0x02, 0xC0, + 0xB9, 0xF9, 0x08, 0x80, 0x0C, 0xFB, 0x08, 0x33, 0xB2, 0xF9, 0x04, 0xC0, 0xB9, 0xF9, 0x0A, 0x80, + 0x02, 0xEB, 0x4E, 0x02, 0x0C, 0xFB, 0x08, 0x3B, 0xB2, 0xF9, 0x00, 0xC0, 0xB9, 0xF9, 0x0C, 0x80, + 0x0C, 0xFB, 0x08, 0xB3, 0xB2, 0xF9, 0x02, 0xC0, 0xB9, 0xF9, 0x0E, 0x80, 0x0C, 0xFB, 0x08, 0x33, + 0xB2, 0xF9, 0x04, 0xC0, 0xB9, 0xF9, 0x10, 0x20, 0x0C, 0xFB, 0x02, 0x32, 0x92, 0xFB, 0xFA, 0xF2, + 0x01, 0x9B, 0x23, 0xF8, 0x11, 0x20, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xB0, 0xD9, 0x6D, 0x1C, + 0xED, 0xB2, 0xBD, 0x42, 0x9A, 0xD9, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1C, 0xB5, 0x0E, 0x4C, + 0x24, 0x68, 0x01, 0x94, 0x01, 0xAC, 0x00, 0x94, 0xFF, 0xF7, 0xF1, 0xFE, 0x1C, 0xBD, 0x38, 0xB5, + 0x0D, 0x4D, 0x00, 0x90, 0x09, 0x48, 0x0C, 0x46, 0x09, 0x4A, 0x00, 0x68, 0xB0, 0xF9, 0xE2, 0x32, + 0x08, 0x48, 0x01, 0x68, 0x28, 0x68, 0xFF, 0xF7, 0xE2, 0xFE, 0x28, 0x68, 0xA0, 0x60, 0x38, 0xBD, + 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x64, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x3E, 0x6C, 0x01, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x34, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x5F, + 0x89, 0x46, 0x14, 0x46, 0x91, 0x78, 0x0F, 0x9D, 0x09, 0xF0, 0x0C, 0xFD, 0x82, 0x46, 0xA1, 0x78, + 0xA8, 0x68, 0x09, 0xF0, 0x0D, 0xFD, 0x47, 0xF6, 0xFF, 0x76, 0xA7, 0x78, 0xF5, 0x43, 0xFE, 0x49, + 0x94, 0xF8, 0x03, 0x80, 0x91, 0xF8, 0x00, 0xB0, 0x18, 0xE0, 0x22, 0x78, 0x94, 0xF8, 0x01, 0xC0, + 0x0D, 0xE0, 0x00, 0xBF, 0x1A, 0xF8, 0x02, 0x10, 0x49, 0x45, 0x07, 0xD1, 0x30, 0xF9, 0x12, 0x30, + 0xB3, 0x42, 0x00, 0xDA, 0x1E, 0x46, 0xAB, 0x42, 0x00, 0xDD, 0x1D, 0x46, 0x52, 0x1C, 0x94, 0x45, + 0xF0, 0xD2, 0x0A, 0xF1, 0x28, 0x0A, 0x00, 0xEB, 0x4B, 0x00, 0x7F, 0x1C, 0xB8, 0x45, 0xE4, 0xD2, + 0x03, 0x98, 0x06, 0x80, 0x0E, 0x98, 0x05, 0x80, 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xFF, 0x4F, + 0xEA, 0x48, 0x85, 0xB0, 0x9A, 0x46, 0x04, 0x68, 0x03, 0xA9, 0xCD, 0xE9, 0x00, 0x1A, 0xDD, 0xE9, + 0x05, 0x01, 0x15, 0x46, 0x04, 0xF5, 0x88, 0x79, 0x02, 0xAB, 0xFF, 0xF7, 0xB7, 0xFF, 0xE4, 0x48, + 0xBD, 0xF9, 0x0C, 0x20, 0xDF, 0xF8, 0x8C, 0xB3, 0x00, 0x68, 0x5F, 0x46, 0x90, 0xF8, 0xE4, 0x12, + 0xBD, 0xF9, 0x08, 0x00, 0x12, 0x1A, 0x4A, 0x43, 0x64, 0x21, 0x92, 0xFB, 0xF1, 0xF1, 0x0E, 0x18, + 0x01, 0x22, 0x29, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0xFF, 0xF7, 0xBC, 0xFA, 0xD7, 0xF8, 0x00, 0x80, + 0xDD, 0xE9, 0x05, 0x07, 0x31, 0xB2, 0x01, 0x91, 0xA9, 0x78, 0x09, 0xF0, 0xAB, 0xFC, 0x06, 0x46, + 0xA9, 0x78, 0x40, 0x46, 0x09, 0xF0, 0xB4, 0xFC, 0x00, 0x90, 0xA9, 0x78, 0xDA, 0xF8, 0x08, 0x00, + 0x09, 0xF0, 0xA6, 0xFC, 0x01, 0x46, 0xAA, 0x78, 0x01, 0x23, 0xDF, 0xF8, 0x2C, 0xE3, 0x1D, 0xE0, + 0x28, 0x78, 0x0E, 0xE0, 0x16, 0xF8, 0x00, 0xC0, 0xBC, 0x45, 0x09, 0xD1, 0x31, 0xF9, 0x10, 0x80, + 0xDD, 0xF8, 0x04, 0xC0, 0xE0, 0x45, 0x03, 0xDD, 0xDD, 0xF8, 0x00, 0xC0, 0x0C, 0xF8, 0x00, 0x30, + 0x40, 0x1C, 0x95, 0xF8, 0x01, 0xC0, 0x84, 0x45, 0xEC, 0xD2, 0x00, 0x98, 0x52, 0x1C, 0x28, 0x30, + 0x00, 0x90, 0x9E, 0xF8, 0x00, 0x00, 0x28, 0x36, 0x01, 0xEB, 0x40, 0x01, 0xE8, 0x78, 0x90, 0x42, + 0xDE, 0xD2, 0x00, 0x20, 0x84, 0xF8, 0x0E, 0x01, 0x28, 0x68, 0x20, 0x60, 0x01, 0x23, 0x00, 0x22, + 0x21, 0x46, 0x5E, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0xFF, 0xF7, 0x76, 0xFB, 0x94, 0xF8, 0x0E, 0x01, + 0x01, 0x28, 0x26, 0xD9, 0x01, 0x25, 0x1D, 0xE0, 0x48, 0x22, 0x51, 0x46, 0x48, 0x46, 0x09, 0xF0, + 0x1E, 0xFB, 0x04, 0xEB, 0x45, 0x00, 0x04, 0xEB, 0x85, 0x07, 0xB0, 0xF8, 0xB4, 0x10, 0xA9, 0xF8, + 0x26, 0x10, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x33, 0xFD, 0x3A, 0x46, 0xE9, 0xB2, 0x4B, 0x46, + 0x30, 0x68, 0xFE, 0xF7, 0xC4, 0xFB, 0x3A, 0x46, 0xE9, 0xB2, 0x4B, 0x46, 0x30, 0x68, 0xFE, 0xF7, + 0x3B, 0xFB, 0x6D, 0x1C, 0x94, 0xF8, 0x0E, 0x01, 0xA8, 0x42, 0xDD, 0xD2, 0x09, 0xB0, 0xBD, 0xE8, + 0xF0, 0x8F, 0xDD, 0xE9, 0x05, 0x01, 0x53, 0x46, 0x2A, 0x46, 0xFE, 0xF7, 0x2D, 0xFB, 0xF5, 0xE7, + 0x2D, 0xE9, 0xFE, 0x4F, 0x06, 0x46, 0x9A, 0x48, 0x1D, 0x46, 0x0B, 0x46, 0x00, 0x68, 0x9A, 0x49, + 0x0E, 0x9C, 0xB0, 0xF9, 0xE6, 0x92, 0x89, 0x79, 0x93, 0x46, 0x09, 0xB1, 0xB0, 0xF9, 0x62, 0x93, + 0x96, 0x49, 0x09, 0x78, 0x09, 0xB1, 0xB0, 0xF9, 0xF4, 0x92, 0x18, 0x46, 0x0C, 0x99, 0x09, 0xF0, + 0x21, 0xFC, 0x82, 0x46, 0x30, 0x46, 0x0C, 0x99, 0x09, 0xF0, 0x2A, 0xFC, 0x01, 0x90, 0xA0, 0x68, + 0x0C, 0x99, 0x09, 0xF0, 0x1D, 0xFC, 0x2C, 0x78, 0x6D, 0x78, 0x80, 0x46, 0x64, 0xB9, 0x9A, 0xF8, + 0x00, 0x10, 0x59, 0x45, 0x07, 0xD1, 0xB8, 0xF9, 0x00, 0x10, 0x0D, 0x98, 0x81, 0x42, 0x02, 0xDD, + 0x01, 0x99, 0x01, 0x20, 0x08, 0x70, 0x01, 0x24, 0x7F, 0x48, 0x00, 0x78, 0x40, 0x1E, 0x85, 0x42, + 0x55, 0xD1, 0x1A, 0xF8, 0x05, 0x10, 0x59, 0x45, 0x07, 0xD1, 0x38, 0xF9, 0x15, 0x10, 0x0D, 0x98, + 0x81, 0x42, 0x02, 0xDD, 0x01, 0x99, 0x01, 0x20, 0x48, 0x55, 0x6D, 0x1E, 0xED, 0xB2, 0x46, 0xE0, + 0x1A, 0xF8, 0x04, 0x10, 0x59, 0x45, 0x41, 0xD1, 0x38, 0xF9, 0x14, 0x10, 0x0D, 0x98, 0x02, 0x91, + 0x81, 0x42, 0x3B, 0xDD, 0x00, 0x20, 0x00, 0x90, 0x75, 0x49, 0x0C, 0x98, 0x22, 0x46, 0x01, 0xEB, + 0xC0, 0x00, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67, 0x01, 0x20, 0x09, 0xF0, 0x1C, 0xFA, 0x06, 0x40, + 0x0F, 0x40, 0x3E, 0x43, 0x27, 0xD1, 0x02, 0x98, 0x08, 0xEB, 0x44, 0x02, 0x48, 0x44, 0x32, 0xF9, + 0x02, 0x1C, 0x00, 0xB2, 0x81, 0x42, 0x05, 0xDD, 0xB2, 0xF9, 0x02, 0x30, 0x83, 0x42, 0x01, 0xDD, + 0x01, 0x23, 0x00, 0x93, 0x01, 0x2C, 0x09, 0xD9, 0x32, 0xF9, 0x04, 0x3C, 0x83, 0x42, 0x05, 0xDD, + 0xB2, 0xF9, 0x02, 0x30, 0x83, 0x42, 0x01, 0xDD, 0x01, 0x23, 0x00, 0x93, 0x5A, 0x4B, 0x1B, 0x78, + 0x9B, 0x1E, 0x9C, 0x42, 0x05, 0xD2, 0x81, 0x42, 0x03, 0xDD, 0xB2, 0xF9, 0x04, 0x10, 0x81, 0x42, + 0x04, 0xDC, 0x00, 0x98, 0x10, 0xB9, 0x01, 0x99, 0x01, 0x20, 0x08, 0x55, 0x64, 0x1C, 0xAC, 0x42, + 0xB6, 0xD9, 0xBD, 0xE8, 0xFE, 0x8F, 0x2D, 0xE9, 0xFF, 0x4F, 0x54, 0x48, 0x9B, 0xB0, 0xDF, 0xF8, + 0x48, 0x91, 0x01, 0x78, 0x4E, 0x48, 0x28, 0x9E, 0x1D, 0x46, 0x00, 0x68, 0x39, 0xB1, 0x90, 0xF8, + 0xF3, 0x42, 0xB0, 0xF9, 0xF4, 0x12, 0x11, 0x91, 0xB0, 0xF9, 0xF6, 0x02, 0x11, 0xE0, 0x99, 0xF8, + 0x06, 0x10, 0x39, 0xB1, 0x90, 0xF8, 0x68, 0x43, 0xB0, 0xF9, 0x62, 0x13, 0x11, 0x91, 0xB0, 0xF9, + 0x64, 0x03, 0x06, 0xE0, 0x90, 0xF8, 0xE5, 0x42, 0xB0, 0xF9, 0xE6, 0x12, 0x11, 0x91, 0xB0, 0xF9, + 0xE8, 0x02, 0x44, 0x4F, 0x83, 0x46, 0xAC, 0xB1, 0x04, 0xA8, 0xCD, 0xE9, 0x00, 0x06, 0xDD, 0xE9, + 0x1C, 0x01, 0x02, 0xAB, 0x2A, 0x46, 0xFF, 0xF7, 0x61, 0xFE, 0xBD, 0xF9, 0x10, 0x00, 0xBD, 0xF9, + 0x08, 0x10, 0x40, 0x1A, 0x60, 0x43, 0x64, 0x21, 0x90, 0xFB, 0xF1, 0xF0, 0x39, 0x88, 0x08, 0x44, + 0x00, 0xB2, 0x01, 0xE0, 0xB7, 0xF9, 0x00, 0x00, 0xAC, 0x78, 0x95, 0xF8, 0x03, 0x80, 0x82, 0x46, + 0x4C, 0xB9, 0xCD, 0xE9, 0x00, 0x4A, 0x1B, 0xAF, 0x02, 0x96, 0x97, 0xE8, 0x07, 0x00, 0x2B, 0x46, + 0xFF, 0xF7, 0x1E, 0xFF, 0x01, 0x24, 0x30, 0x48, 0x00, 0x78, 0x40, 0x1E, 0x80, 0x45, 0x0D, 0xD1, + 0xCD, 0xF8, 0x00, 0x80, 0xCD, 0xE9, 0x01, 0xA6, 0x1B, 0xAF, 0x2B, 0x46, 0x97, 0xE8, 0x07, 0x00, + 0xFF, 0xF7, 0x0E, 0xFF, 0xA8, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x08, 0xA0, 0x1E, 0xC1, 0xB2, + 0xB0, 0x68, 0x09, 0xF0, 0x45, 0xFB, 0x09, 0x90, 0x60, 0x1E, 0xC1, 0xB2, 0xB0, 0x68, 0x09, 0xF0, + 0x3F, 0xFB, 0x0B, 0x90, 0x21, 0x46, 0xB0, 0x68, 0x09, 0xF0, 0x3A, 0xFB, 0x06, 0x90, 0x60, 0x1C, + 0xC1, 0xB2, 0xB0, 0x68, 0x09, 0xF0, 0x34, 0xFB, 0x05, 0x90, 0xA0, 0x1C, 0xC1, 0xB2, 0xB0, 0x68, + 0x09, 0xF0, 0x2E, 0xFB, 0x0C, 0x90, 0x21, 0x46, 0x1C, 0x98, 0x09, 0xF0, 0x23, 0xFB, 0x07, 0x90, + 0x21, 0x46, 0x1B, 0x98, 0x09, 0xF0, 0x2C, 0xFB, 0x02, 0x90, 0x00, 0x20, 0x14, 0x90, 0x01, 0x20, + 0x13, 0x90, 0x00, 0x20, 0x12, 0x90, 0x99, 0xF8, 0x04, 0x00, 0x58, 0xB3, 0x08, 0x48, 0x00, 0x68, + 0x90, 0xF8, 0x40, 0x14, 0x09, 0x07, 0x25, 0xD5, 0x6A, 0x78, 0x29, 0x78, 0x52, 0x1A, 0x90, 0xF8, + 0x4B, 0x14, 0x52, 0x1C, 0x8A, 0x42, 0x11, 0xE0, 0xBA, 0x06, 0x10, 0x00, 0x48, 0x06, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x30, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, + 0x48, 0x3F, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x0A, 0xDC, 0xEA, 0x78, + 0xAB, 0x78, 0xD2, 0x1A, 0x52, 0x1C, 0x8A, 0x42, 0x04, 0xDC, 0xB0, 0xF8, 0x49, 0x04, 0xB1, 0x69, + 0x81, 0x42, 0x01, 0xDD, 0x00, 0x20, 0x13, 0x90, 0xA1, 0x46, 0xE0, 0xE0, 0x2C, 0x78, 0xBC, 0xE0, + 0x07, 0x98, 0x01, 0x5D, 0x1D, 0x98, 0x81, 0x42, 0x67, 0xD1, 0x00, 0x20, 0x10, 0x90, 0xFD, 0x49, + 0x16, 0x90, 0x15, 0x90, 0x01, 0xEB, 0xC9, 0x00, 0x22, 0x46, 0xD0, 0xE9, 0x00, 0x67, 0x01, 0x20, + 0x00, 0x21, 0x09, 0xF0, 0x10, 0xF9, 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x7D, 0xD1, 0x06, 0x98, + 0x0B, 0x9A, 0x30, 0xF8, 0x14, 0x10, 0x11, 0x98, 0x32, 0xF9, 0x14, 0x20, 0x08, 0x44, 0x00, 0xB2, + 0x59, 0x44, 0x09, 0xB2, 0x82, 0x42, 0x07, 0xDD, 0x05, 0x9B, 0x33, 0xF9, 0x14, 0x30, 0x83, 0x42, + 0x02, 0xDD, 0x01, 0x23, 0x10, 0x93, 0x15, 0x93, 0xF4, 0xB3, 0xEB, 0x4B, 0x1B, 0x78, 0x5E, 0x1E, + 0xB4, 0x42, 0x68, 0xD0, 0x06, 0x9E, 0x06, 0xEB, 0x44, 0x0E, 0x3E, 0xF9, 0x02, 0x6C, 0x86, 0x42, + 0x06, 0xDD, 0xBE, 0xF9, 0x02, 0x70, 0x87, 0x42, 0x02, 0xDD, 0x01, 0x27, 0x10, 0x97, 0x16, 0x97, + 0x0B, 0x9F, 0x07, 0xEB, 0x44, 0x07, 0x37, 0xF9, 0x02, 0xCC, 0x8C, 0x45, 0x0B, 0xDD, 0xDD, 0xF8, + 0x14, 0xC0, 0x0C, 0xEB, 0x44, 0x0C, 0xBC, 0xF9, 0x02, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, + 0x01, 0x0C, 0xCD, 0xF8, 0x40, 0xC0, 0xB7, 0xF9, 0x02, 0x70, 0x8F, 0x42, 0x06, 0xDD, 0x05, 0x9F, + 0x07, 0xEB, 0x44, 0x07, 0x37, 0xF9, 0x02, 0x7C, 0x8F, 0x42, 0x47, 0xDC, 0x10, 0x99, 0xA9, 0xBB, + 0xB9, 0xF1, 0x01, 0x0F, 0x0F, 0xD9, 0x09, 0x99, 0x31, 0xF9, 0x14, 0x10, 0x81, 0x42, 0x0A, 0xDD, + 0x05, 0x99, 0x31, 0xF9, 0x14, 0x10, 0x01, 0xE0, 0x2D, 0xE0, 0x4D, 0xE0, 0x81, 0x42, 0x02, 0xDD, + 0x01, 0x21, 0x10, 0x91, 0x15, 0x91, 0xC9, 0x4F, 0x3F, 0x78, 0xBF, 0x1E, 0xB9, 0x45, 0x09, 0xD2, + 0x82, 0x42, 0x07, 0xDD, 0x0C, 0x99, 0x31, 0xF9, 0x14, 0x10, 0x81, 0x42, 0x02, 0xDD, 0x01, 0x21, + 0x10, 0x91, 0x15, 0x91, 0x01, 0x2C, 0x0A, 0xD9, 0x3E, 0xF9, 0x04, 0x1C, 0x81, 0x42, 0x06, 0xDD, + 0xBE, 0xF9, 0x02, 0x10, 0x81, 0x42, 0x02, 0xDD, 0x01, 0x21, 0x10, 0x91, 0x16, 0x91, 0x9B, 0x1E, + 0x9C, 0x42, 0x08, 0xD2, 0x86, 0x42, 0x06, 0xDD, 0x01, 0xE0, 0x06, 0xE0, 0x0E, 0xE0, 0xBE, 0xF9, + 0x04, 0x10, 0x81, 0x42, 0x0C, 0xDC, 0x10, 0x98, 0x40, 0xB9, 0x06, 0x98, 0x30, 0xF9, 0x14, 0x10, + 0x51, 0x45, 0x03, 0xDD, 0x02, 0x99, 0x01, 0x20, 0x08, 0x55, 0x15, 0xE0, 0x16, 0x98, 0x98, 0xB1, + 0x15, 0x98, 0x88, 0xB1, 0x13, 0x98, 0x78, 0xB1, 0x02, 0x99, 0x01, 0x20, 0x08, 0x55, 0x12, 0x98, + 0x40, 0x1C, 0x80, 0xB2, 0x12, 0x90, 0xAA, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x4C, 0x14, 0x12, 0x98, + 0x81, 0x42, 0x01, 0xD2, 0x01, 0x20, 0x14, 0x90, 0x64, 0x1C, 0x68, 0x78, 0xA0, 0x42, 0xBF, 0xF4, + 0x3F, 0xAF, 0xA1, 0x48, 0x09, 0x99, 0x09, 0xF1, 0x01, 0x09, 0x00, 0x78, 0x01, 0xEB, 0x40, 0x01, + 0x09, 0x91, 0x0B, 0x99, 0x01, 0xEB, 0x40, 0x01, 0x0B, 0x91, 0x06, 0x99, 0x01, 0xEB, 0x40, 0x01, + 0x06, 0x91, 0x05, 0x99, 0x01, 0xEB, 0x40, 0x01, 0x05, 0x91, 0x0C, 0x99, 0x01, 0xEB, 0x40, 0x00, + 0x0C, 0x90, 0x07, 0x98, 0x28, 0x30, 0x07, 0x90, 0x02, 0x98, 0x28, 0x30, 0x02, 0x90, 0xC1, 0x45, + 0x7F, 0xF6, 0x1C, 0xAF, 0x14, 0x98, 0x1F, 0xB0, 0xB9, 0xE5, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, + 0x91, 0x42, 0x5A, 0xD0, 0x07, 0xD9, 0x01, 0xEB, 0x02, 0x00, 0xA0, 0xEB, 0x02, 0x01, 0xCA, 0xB2, + 0xA0, 0xEB, 0x02, 0x00, 0xC1, 0xB2, 0x01, 0xEB, 0xC1, 0x00, 0x04, 0xEB, 0xC0, 0x01, 0x02, 0xEB, + 0xC2, 0x00, 0x04, 0xEB, 0xC0, 0x00, 0xB1, 0xF9, 0x32, 0x50, 0xB0, 0xF9, 0x32, 0x30, 0x81, 0x46, + 0x9D, 0x42, 0x00, 0xDA, 0x4B, 0x86, 0xCB, 0x8C, 0xC5, 0x8C, 0x2B, 0x44, 0xCB, 0x84, 0x0B, 0x8D, + 0x05, 0x8D, 0x2B, 0x44, 0x0B, 0x85, 0x4B, 0x8D, 0x45, 0x8D, 0x2B, 0x44, 0x4B, 0x85, 0x8B, 0x69, + 0x85, 0x69, 0x2B, 0x44, 0x8B, 0x61, 0xC7, 0x69, 0xCE, 0x69, 0xCB, 0x68, 0xD9, 0xF8, 0x0C, 0x00, + 0x4F, 0xEA, 0x23, 0x4C, 0x4F, 0xEA, 0x20, 0x48, 0x0C, 0xFB, 0x06, 0xFC, 0xF5, 0x19, 0x07, 0xFB, + 0x08, 0xCC, 0x9C, 0xFB, 0xF5, 0xFC, 0x6C, 0xF3, 0x1F, 0x43, 0x0F, 0xFA, 0x83, 0xFC, 0x0C, 0xFB, + 0x06, 0xFC, 0x00, 0xB2, 0x07, 0xFB, 0x00, 0xC0, 0x90, 0xFB, 0xF5, 0xF0, 0x60, 0xF3, 0x0F, 0x03, + 0xCD, 0x61, 0xCB, 0x60, 0x94, 0xF8, 0x38, 0x04, 0x41, 0x1E, 0x91, 0x42, 0x08, 0xD0, 0x00, 0xEB, + 0xC0, 0x00, 0x04, 0xEB, 0xC0, 0x01, 0x48, 0x46, 0x48, 0x22, 0x48, 0x39, 0x09, 0xF0, 0x5F, 0xF8, + 0x94, 0xF8, 0x38, 0x04, 0x40, 0x1E, 0x84, 0xF8, 0x38, 0x04, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, + 0xFE, 0x4F, 0x07, 0x46, 0x5E, 0x48, 0x8A, 0x46, 0x00, 0x25, 0x01, 0x68, 0xB1, 0xF8, 0xEA, 0x02, + 0x00, 0xFB, 0x00, 0xF9, 0x5B, 0x48, 0x80, 0x79, 0x18, 0xB1, 0xB1, 0xF8, 0x66, 0x03, 0x00, 0xFB, + 0x00, 0xF9, 0x54, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x9D, 0xE0, 0x00, 0xBF, 0x0B, 0xFA, 0x04, 0xF0, + 0x26, 0x46, 0x00, 0x90, 0x66, 0xE0, 0x00, 0xBF, 0x00, 0x99, 0x0B, 0xFA, 0x06, 0xF0, 0x08, 0x42, + 0x5F, 0xD0, 0x06, 0xEB, 0xC6, 0x00, 0x07, 0xEB, 0xC0, 0x00, 0xC2, 0x68, 0x20, 0x46, 0x4D, 0xE0, + 0xB0, 0x42, 0x4A, 0xD0, 0x00, 0xEB, 0xC0, 0x01, 0x07, 0xEB, 0xC1, 0x01, 0xC9, 0x68, 0x4F, 0xEA, + 0x21, 0x4C, 0xAC, 0xEB, 0x22, 0x4C, 0x89, 0x1A, 0x0F, 0xFA, 0x8C, 0xFC, 0x09, 0xB2, 0x6C, 0xF3, + 0x1F, 0x45, 0x61, 0xF3, 0x0F, 0x05, 0x8E, 0x46, 0x41, 0x49, 0xCD, 0xF8, 0x04, 0xC0, 0x09, 0x68, + 0x91, 0xF8, 0xE0, 0xC2, 0xCD, 0xF8, 0x08, 0xC0, 0x5F, 0xEA, 0x8C, 0x6C, 0x0B, 0xD5, 0x91, 0xF8, + 0xED, 0x82, 0x0E, 0xFB, 0x08, 0xFC, 0x4F, 0xF0, 0x64, 0x08, 0x9C, 0xFB, 0xF8, 0xF8, 0x08, 0xEB, + 0x0E, 0x0C, 0x6C, 0xF3, 0x0F, 0x05, 0xDD, 0xF8, 0x08, 0xC0, 0x5F, 0xEA, 0xCC, 0x6C, 0x0C, 0xD5, + 0x91, 0xF8, 0xED, 0x12, 0xDD, 0xF8, 0x04, 0xC0, 0x0C, 0xFB, 0x01, 0xFC, 0x64, 0x21, 0x9C, 0xFB, + 0xF1, 0xFC, 0x01, 0x99, 0x61, 0x44, 0x61, 0xF3, 0x1F, 0x45, 0x4F, 0xEA, 0x25, 0x4C, 0x0C, 0xFB, + 0x0C, 0xFC, 0x29, 0xB2, 0x01, 0xFB, 0x01, 0xC1, 0x49, 0x45, 0x06, 0xD2, 0xDD, 0xF8, 0x00, 0xC0, + 0x0B, 0xFA, 0x00, 0xF1, 0x41, 0xEA, 0x0C, 0x01, 0x00, 0x91, 0x40, 0x1C, 0x83, 0x42, 0xAF, 0xD8, + 0x04, 0x21, 0x68, 0x46, 0x07, 0xF0, 0xD6, 0xFC, 0x01, 0x28, 0x02, 0xD1, 0x00, 0x98, 0x40, 0x00, + 0x00, 0x90, 0x76, 0x1C, 0x97, 0xF8, 0x38, 0x34, 0xB3, 0x42, 0x95, 0xD8, 0x04, 0x21, 0x68, 0x46, + 0x07, 0xF0, 0xC8, 0xFC, 0x01, 0x28, 0x0B, 0xD0, 0x04, 0x21, 0x68, 0x46, 0x07, 0xF0, 0xC2, 0xFC, + 0x97, 0xF8, 0x38, 0x64, 0xA6, 0xEB, 0x0A, 0x01, 0x88, 0x42, 0x05, 0xD1, 0x87, 0xF8, 0x38, 0xA4, + 0x57, 0xE5, 0x64, 0x1C, 0xE4, 0xB2, 0x01, 0xE0, 0x00, 0x99, 0x58, 0x46, 0x00, 0xFA, 0x04, 0xF2, + 0x0A, 0x42, 0xF6, 0xD0, 0xD8, 0x46, 0x09, 0xE0, 0x00, 0x99, 0x08, 0xFA, 0x06, 0xF0, 0x08, 0x42, + 0x04, 0xD0, 0xF2, 0xB2, 0x21, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xEF, 0xFE, 0x76, 0x1E, 0xA6, 0x42, + 0xF2, 0xD8, 0x64, 0x1C, 0xE4, 0xB2, 0x97, 0xF8, 0x38, 0x04, 0xA0, 0x42, 0x3F, 0xF6, 0x5E, 0xAF, + 0x37, 0xE5, 0x00, 0x00, 0x48, 0x3F, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xFE, 0x4C, 0x01, 0x2B, + 0x24, 0x68, 0x94, 0xF8, 0xF9, 0x72, 0x94, 0xF8, 0xF8, 0x62, 0x05, 0xD0, 0x0B, 0x78, 0x4C, 0x78, + 0xFA, 0x4D, 0x9C, 0x46, 0x69, 0x0C, 0x0D, 0xE0, 0x8B, 0x78, 0xCC, 0x78, 0xF8, 0xE7, 0x00, 0xBF, + 0x30, 0xF9, 0x1C, 0x80, 0xA8, 0x45, 0x00, 0xDD, 0x45, 0x46, 0x88, 0x45, 0x00, 0xDA, 0x41, 0x46, + 0x0C, 0xF1, 0x01, 0x0C, 0xA4, 0x45, 0xF3, 0xD9, 0xB5, 0x42, 0x00, 0xDA, 0x35, 0x46, 0xB1, 0x42, + 0x00, 0xDA, 0x31, 0x46, 0x69, 0x1A, 0x79, 0x43, 0x64, 0x25, 0x91, 0xFB, 0xF5, 0xF1, 0x31, 0x44, + 0x0E, 0xB2, 0x30, 0xF9, 0x13, 0x50, 0x01, 0x21, 0xB5, 0x42, 0x05, 0xDD, 0x15, 0x68, 0x01, 0xFA, + 0x03, 0xFC, 0x45, 0xEA, 0x0C, 0x05, 0x15, 0x60, 0x30, 0xF9, 0x14, 0x50, 0xB5, 0x42, 0x05, 0xDD, + 0x15, 0x68, 0x01, 0xFA, 0x04, 0xFC, 0x45, 0xEA, 0x0C, 0x05, 0x15, 0x60, 0xE5, 0x1A, 0x05, 0xF0, + 0xFF, 0x09, 0xB9, 0xF1, 0x01, 0x0F, 0x37, 0xD9, 0x5D, 0x1C, 0xED, 0xB2, 0x30, 0xF9, 0x15, 0x80, + 0x08, 0xEB, 0x07, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC, 0xB0, 0x45, 0x11, 0xDD, 0x00, 0xEB, 0x45, 0x0A, + 0x3A, 0xF9, 0x02, 0x8C, 0xE0, 0x45, 0x03, 0xDD, 0xBA, 0xF9, 0x02, 0x80, 0xE0, 0x45, 0x07, 0xDC, + 0xD2, 0xF8, 0x00, 0xC0, 0x01, 0xFA, 0x05, 0xF5, 0x4C, 0xEA, 0x05, 0x0C, 0xC2, 0xF8, 0x00, 0xC0, + 0x65, 0x1E, 0xED, 0xB2, 0x30, 0xF9, 0x15, 0x80, 0x08, 0xEB, 0x07, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC, + 0xB0, 0x45, 0x11, 0xDD, 0x00, 0xEB, 0x45, 0x0A, 0x3A, 0xF9, 0x02, 0x8C, 0xE0, 0x45, 0x03, 0xDD, + 0xBA, 0xF9, 0x02, 0x80, 0xE0, 0x45, 0x07, 0xDC, 0xD2, 0xF8, 0x00, 0xC0, 0x01, 0xFA, 0x05, 0xF5, + 0x4C, 0xEA, 0x05, 0x0C, 0xC2, 0xF8, 0x00, 0xC0, 0xB9, 0xF1, 0x02, 0x0F, 0x2E, 0xD9, 0x9D, 0x1C, + 0xA4, 0xF1, 0x02, 0x09, 0x28, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x15, 0xC0, 0xB4, 0x45, 0x22, 0xDD, + 0x00, 0xEB, 0x45, 0x0B, 0xBC, 0x44, 0x3B, 0xF9, 0x02, 0xEC, 0x0F, 0xFA, 0x8C, 0xFA, 0xD6, 0x45, + 0x03, 0xDD, 0xBB, 0xF9, 0x02, 0x80, 0xD0, 0x45, 0x15, 0xDC, 0x3B, 0xF9, 0x04, 0x8C, 0xD0, 0x45, + 0x03, 0xDD, 0xBB, 0xF9, 0x02, 0x80, 0xD0, 0x45, 0x0D, 0xDC, 0xD6, 0x45, 0x03, 0xDD, 0xBB, 0xF9, + 0x04, 0x80, 0xD0, 0x45, 0x07, 0xDC, 0xD2, 0xF8, 0x00, 0xC0, 0x01, 0xFA, 0x05, 0xF8, 0x4C, 0xEA, + 0x08, 0x0C, 0xC2, 0xF8, 0x00, 0xC0, 0x6D, 0x1C, 0x4D, 0x45, 0xD5, 0xD9, 0x00, 0x25, 0x28, 0x46, + 0x0C, 0xE0, 0x00, 0xBF, 0x16, 0x68, 0x01, 0xFA, 0x03, 0xF7, 0x3E, 0x42, 0x04, 0xD0, 0x25, 0xB9, + 0x01, 0x25, 0x40, 0x1C, 0xC0, 0xB2, 0x00, 0xE0, 0x00, 0x25, 0x5B, 0x1C, 0xA3, 0x42, 0xF1, 0xD9, + 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xFF, 0x4F, 0x9D, 0x48, 0x8F, 0xB0, 0xDF, 0xF8, 0x74, 0x92, + 0x04, 0x68, 0x16, 0x46, 0x04, 0xF5, 0x88, 0x70, 0x02, 0x90, 0x4F, 0xF0, 0xFF, 0x30, 0x0C, 0x90, + 0x00, 0x20, 0x0A, 0x90, 0x0B, 0x90, 0x98, 0x46, 0x01, 0x22, 0x31, 0x46, 0x4D, 0x46, 0xD9, 0xF8, + 0x00, 0x00, 0xFE, 0xF7, 0xFF, 0xFD, 0xCD, 0xF8, 0x00, 0x80, 0xDD, 0xE9, 0x0F, 0x12, 0x33, 0x46, + 0x28, 0x68, 0xFF, 0xF7, 0x48, 0xFC, 0x05, 0x00, 0x08, 0xD0, 0x8F, 0x49, 0x01, 0x20, 0x08, 0x70, + 0xB8, 0xF8, 0x24, 0x00, 0x40, 0xF0, 0x80, 0x01, 0xA8, 0xF8, 0x24, 0x10, 0x8B, 0x48, 0x00, 0x78, + 0x50, 0xB1, 0x4D, 0xB9, 0x98, 0xF8, 0x24, 0x00, 0x10, 0xF0, 0x06, 0x0F, 0x04, 0xD1, 0x31, 0x46, + 0x40, 0x46, 0xFE, 0xF7, 0x3D, 0xFE, 0x05, 0x46, 0x85, 0x48, 0x00, 0x78, 0x00, 0xB1, 0x01, 0x25, + 0x7D, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xE1, 0x02, 0x40, 0x07, 0x2F, 0xD5, 0x01, 0x23, 0x0A, 0xAA, + 0x31, 0x46, 0x80, 0x48, 0xFF, 0xF7, 0xF0, 0xFE, 0x07, 0x46, 0x00, 0x23, 0x0B, 0xAA, 0x31, 0x46, + 0x7D, 0x48, 0xFF, 0xF7, 0xE9, 0xFE, 0x78, 0x43, 0x01, 0x28, 0x1F, 0xD1, 0xB7, 0x78, 0x1A, 0xE0, + 0xF9, 0xB2, 0x0F, 0x98, 0x08, 0xF0, 0xC4, 0xFF, 0x83, 0x46, 0xF9, 0xB2, 0xD9, 0xF8, 0x00, 0x00, + 0x08, 0xF0, 0xBE, 0xFF, 0x02, 0x46, 0x30, 0x78, 0x01, 0x23, 0x08, 0xE0, 0x1B, 0xF8, 0x00, 0xC0, + 0x10, 0x99, 0x8C, 0x45, 0x02, 0xD1, 0x11, 0x5C, 0x01, 0xB9, 0x13, 0x54, 0x40, 0x1C, 0x71, 0x78, + 0x81, 0x42, 0xF3, 0xDA, 0x7F, 0x1C, 0xF0, 0x78, 0xB8, 0x42, 0xE1, 0xDA, 0x00, 0x20, 0x84, 0xF8, + 0x0E, 0x01, 0x30, 0x68, 0x20, 0x60, 0x63, 0x48, 0x2B, 0x46, 0x00, 0x22, 0x21, 0x46, 0x00, 0x68, + 0xFE, 0xF7, 0x9A, 0xFE, 0x94, 0xF8, 0x0E, 0x01, 0x00, 0x25, 0x01, 0x28, 0x70, 0xD9, 0xFC, 0xF7, + 0xB4, 0xFB, 0x83, 0x46, 0xFC, 0xF7, 0xAF, 0xFB, 0x82, 0x46, 0x32, 0x68, 0xDD, 0xE9, 0x0F, 0x01, + 0x07, 0x92, 0x47, 0x46, 0x5D, 0x4B, 0x07, 0xAA, 0xFE, 0xF7, 0x3B, 0xFD, 0x60, 0xB1, 0x07, 0xA9, + 0x5A, 0x48, 0xFE, 0xF7, 0xCF, 0xFC, 0x3A, 0x46, 0x07, 0xA9, 0x58, 0x48, 0xFD, 0xF7, 0x1F, 0xFB, + 0xF8, 0x68, 0x78, 0x61, 0xF8, 0x69, 0x38, 0x62, 0x51, 0x48, 0x00, 0x78, 0xE8, 0xB3, 0x4A, 0x48, + 0x00, 0x68, 0x90, 0xF8, 0xE1, 0x02, 0x80, 0x07, 0x46, 0xD5, 0x94, 0xF8, 0x0E, 0x01, 0x01, 0x28, + 0x42, 0xD9, 0x4F, 0xF0, 0x00, 0x09, 0x01, 0x27, 0x10, 0xE0, 0x00, 0xBF, 0x45, 0x48, 0x04, 0xEB, + 0x87, 0x03, 0xFA, 0xB2, 0xD8, 0xF8, 0x08, 0x10, 0x00, 0x68, 0xFE, 0xF7, 0x89, 0xFD, 0x48, 0x49, + 0x48, 0x45, 0x41, 0xF8, 0x27, 0x00, 0x00, 0xDD, 0x81, 0x46, 0x7F, 0x1C, 0x94, 0xF8, 0x0E, 0x21, + 0xBA, 0x42, 0xEB, 0xD2, 0xB9, 0xF1, 0x00, 0x0F, 0x1F, 0xDD, 0x37, 0x49, 0x01, 0x20, 0x40, 0x4B, + 0x86, 0x46, 0x09, 0x68, 0x17, 0xE0, 0x00, 0xBF, 0x53, 0xF8, 0x20, 0x70, 0x4F, 0xF0, 0x64, 0x0C, + 0x07, 0xFB, 0x0C, 0xF7, 0x97, 0xFB, 0xF9, 0xF7, 0x91, 0xF8, 0xF2, 0xC2, 0xBC, 0x45, 0x09, 0xDD, + 0x0E, 0xFA, 0x00, 0xF7, 0xDD, 0xF8, 0x30, 0xC0, 0x00, 0xE0, 0x0D, 0xE0, 0x2C, 0xEA, 0x07, 0x0C, + 0xCD, 0xF8, 0x30, 0xC0, 0x40, 0x1C, 0x82, 0x42, 0xE6, 0xD2, 0x94, 0xF8, 0x0E, 0x01, 0x01, 0x28, + 0x02, 0xD9, 0x00, 0x20, 0x84, 0xF8, 0x0E, 0x01, 0x01, 0x27, 0xDF, 0xF8, 0x8C, 0x90, 0x35, 0xE0, + 0x7D, 0xE0, 0x48, 0x22, 0x41, 0x46, 0x02, 0x98, 0x08, 0xF0, 0xD1, 0xFD, 0xD9, 0xF8, 0x00, 0x10, + 0x04, 0xEB, 0x47, 0x00, 0xB0, 0xF8, 0xB4, 0x20, 0x91, 0xF8, 0xEC, 0x12, 0x8A, 0x42, 0x24, 0xD9, + 0x01, 0x21, 0x0C, 0x9A, 0xB9, 0x40, 0x11, 0x42, 0x1F, 0xD0, 0x02, 0x99, 0x89, 0x8C, 0x41, 0xF0, + 0x10, 0x02, 0x02, 0x99, 0x8A, 0x84, 0xB0, 0xF8, 0xB4, 0x10, 0x02, 0x98, 0xC1, 0x84, 0x04, 0xEB, + 0x87, 0x00, 0x08, 0x90, 0x02, 0x99, 0xFE, 0xF7, 0xD3, 0xFF, 0x12, 0x48, 0xF9, 0xB2, 0x02, 0x9B, + 0x08, 0x9A, 0x00, 0x68, 0xFD, 0xF7, 0x63, 0xFE, 0x0E, 0x48, 0xF9, 0xB2, 0x02, 0x9B, 0x08, 0x9A, + 0x00, 0x68, 0xFD, 0xF7, 0xD9, 0xFD, 0x6D, 0x1C, 0xED, 0xB2, 0x7F, 0x1C, 0x94, 0xF8, 0x0E, 0x01, + 0xB8, 0x42, 0xC6, 0xD2, 0xD9, 0xF8, 0x00, 0x00, 0x4C, 0x46, 0x90, 0xF8, 0xE0, 0x02, 0x00, 0x07, + 0x21, 0xD5, 0x01, 0x2D, 0x1F, 0xD9, 0x15, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0x48, 0x06, 0x10, 0x00, 0x30, 0x06, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, + 0x28, 0x05, 0x10, 0x00, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, 0xA0, 0x3E, 0x10, 0x00, + 0xA8, 0x40, 0x10, 0x00, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x21, 0xFD, 0xFC, 0xF7, 0xE5, 0xFA, + 0xA0, 0xEB, 0x0B, 0x00, 0xC5, 0xB2, 0x22, 0x68, 0x92, 0xF8, 0xE0, 0x02, 0x00, 0x06, 0x12, 0xD5, + 0x28, 0x46, 0x0E, 0xE0, 0x0B, 0xEB, 0x00, 0x01, 0xC9, 0xB2, 0x01, 0xEB, 0xC1, 0x03, 0x0A, 0xEB, + 0xC3, 0x01, 0x92, 0xF8, 0x07, 0x33, 0xC9, 0x8C, 0x99, 0x42, 0x02, 0xD9, 0x8A, 0xF8, 0x38, 0xB4, + 0x05, 0xE0, 0x40, 0x1E, 0xEE, 0xD2, 0x01, 0x2D, 0x09, 0xD0, 0x00, 0x2D, 0x05, 0xD1, 0xDD, 0xE9, + 0x0F, 0x01, 0x43, 0x46, 0x32, 0x46, 0xFD, 0xF7, 0x87, 0xFD, 0x13, 0xB0, 0x80, 0xE6, 0xE0, 0x48, + 0x00, 0x78, 0x00, 0x28, 0xF9, 0xD1, 0x9A, 0xF8, 0x38, 0x04, 0x40, 0x1E, 0x8A, 0xF8, 0x38, 0x04, + 0xED, 0xE7, 0x2D, 0xE9, 0xFF, 0x4F, 0xDB, 0x48, 0x81, 0xB0, 0x00, 0x68, 0x90, 0xF8, 0xE1, 0x02, + 0xC0, 0x07, 0x67, 0xD0, 0xA8, 0x21, 0x04, 0x98, 0x08, 0xF0, 0x95, 0xFD, 0x01, 0x25, 0x44, 0xE0, + 0x03, 0x98, 0x00, 0xEB, 0x85, 0x00, 0x82, 0x46, 0x84, 0x78, 0x90, 0xF8, 0x03, 0x90, 0xD2, 0x48, + 0x00, 0x78, 0x40, 0x1E, 0x84, 0x42, 0x01, 0xDA, 0x64, 0x1C, 0xE4, 0xB2, 0xB9, 0xF1, 0x00, 0x0F, + 0x03, 0xD0, 0xA9, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x09, 0x21, 0x46, 0x01, 0x98, 0x08, 0xF0, + 0x61, 0xFE, 0x83, 0x46, 0xA0, 0x46, 0x24, 0xE0, 0x03, 0x98, 0x04, 0x99, 0x10, 0xF8, 0x25, 0x40, + 0x01, 0xEB, 0xC8, 0x00, 0x00, 0x90, 0x12, 0xE0, 0x1B, 0xF8, 0x04, 0x00, 0xA8, 0x42, 0x0C, 0xD1, + 0x00, 0x98, 0x22, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67, 0x01, 0x20, 0x08, 0xF0, 0x8B, 0xFC, + 0x06, 0x43, 0x00, 0x98, 0x0F, 0x43, 0xC0, 0xE9, 0x00, 0x67, 0x64, 0x1C, 0xE4, 0xB2, 0x9A, 0xF8, + 0x01, 0x00, 0xA0, 0x42, 0xE8, 0xD2, 0x08, 0xF1, 0x01, 0x00, 0x0B, 0xF1, 0x28, 0x0B, 0x00, 0xF0, + 0xFF, 0x08, 0xC8, 0x45, 0xD8, 0xD9, 0x6D, 0x1C, 0xED, 0xB2, 0x02, 0x98, 0x85, 0x42, 0xB7, 0xD9, + 0x00, 0x21, 0xB1, 0x4E, 0x13, 0xE0, 0x04, 0x98, 0x00, 0xEB, 0xC1, 0x05, 0x01, 0xF1, 0x01, 0x01, + 0xD5, 0xE9, 0x00, 0x32, 0xDC, 0x18, 0x42, 0xEB, 0x02, 0x00, 0x52, 0x08, 0x4F, 0xEA, 0x33, 0x03, + 0x04, 0xEA, 0x03, 0x04, 0x00, 0xEA, 0x02, 0x00, 0xC5, 0xE9, 0x00, 0x40, 0xC9, 0xB2, 0x30, 0x78, + 0x81, 0x42, 0xE8, 0xD3, 0x05, 0xB0, 0x03, 0xE6, 0xF0, 0xB4, 0x14, 0x68, 0xC3, 0xF8, 0x3A, 0x40, + 0xA0, 0x4C, 0x25, 0x68, 0x95, 0xF8, 0xE0, 0x42, 0xA6, 0x07, 0x13, 0xD4, 0x93, 0xF8, 0x40, 0x60, + 0x01, 0x2E, 0x0F, 0xD0, 0x66, 0x07, 0x13, 0xD5, 0x64, 0x06, 0x09, 0xD5, 0x9B, 0x4C, 0x64, 0x78, + 0x5C, 0xB1, 0xB5, 0xF8, 0xF0, 0x42, 0x9A, 0x4D, 0x64, 0x43, 0x2D, 0x68, 0xA5, 0x42, 0x07, 0xDC, + 0xF0, 0xBC, 0xE7, 0xE5, 0xF0, 0xBC, 0xFF, 0xF7, 0x19, 0xB9, 0xB5, 0xF8, 0xEE, 0x42, 0xF2, 0xE7, + 0xF0, 0xBC, 0xFD, 0xF7, 0xE1, 0xBC, 0x2D, 0xE9, 0xFF, 0x4F, 0x94, 0x78, 0xD7, 0x78, 0x15, 0x78, + 0x56, 0x78, 0x81, 0xB0, 0x98, 0x46, 0x82, 0x46, 0x04, 0xB9, 0x01, 0x24, 0x8A, 0x48, 0x00, 0x78, + 0x40, 0x1E, 0x87, 0x42, 0x01, 0xD1, 0x7F, 0x1E, 0xFF, 0xB2, 0x05, 0xB9, 0x01, 0x25, 0xDF, 0xF8, + 0x24, 0xB2, 0x9B, 0xF8, 0x00, 0x00, 0x40, 0x1E, 0x86, 0x42, 0x01, 0xD1, 0x76, 0x1E, 0xF6, 0xB2, + 0x60, 0x1E, 0xC1, 0xB2, 0xD8, 0xF8, 0x08, 0x00, 0x08, 0xF0, 0xD2, 0xFD, 0x00, 0x90, 0x21, 0x46, + 0xD8, 0xF8, 0x08, 0x00, 0x08, 0xF0, 0xCC, 0xFD, 0x81, 0x46, 0x60, 0x1C, 0xC1, 0xB2, 0xD8, 0xF8, + 0x08, 0x00, 0x08, 0xF0, 0xC5, 0xFD, 0x80, 0x46, 0x21, 0x46, 0x50, 0x46, 0x08, 0xF0, 0xBA, 0xFD, + 0x35, 0xE0, 0x74, 0x4A, 0x29, 0x46, 0xD2, 0xF8, 0x00, 0xA0, 0x24, 0xE0, 0x43, 0x5C, 0x02, 0x9A, + 0x93, 0x42, 0x1E, 0xD1, 0x39, 0xF8, 0x11, 0x30, 0x9A, 0xF8, 0x27, 0x24, 0x1A, 0x44, 0x00, 0x9B, + 0x12, 0xB2, 0x03, 0xEB, 0x41, 0x03, 0x33, 0xF9, 0x02, 0xCC, 0x94, 0x45, 0x05, 0xDD, 0x08, 0xEB, + 0x41, 0x0C, 0xBC, 0xF9, 0x02, 0xC0, 0x94, 0x45, 0x09, 0xDC, 0xB3, 0xF9, 0x02, 0x30, 0x93, 0x42, + 0x07, 0xDD, 0x08, 0xEB, 0x41, 0x03, 0x33, 0xF9, 0x02, 0x3C, 0x93, 0x42, 0x01, 0xDD, 0x01, 0x20, + 0x78, 0xE7, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xD8, 0xD9, 0xCD, 0xF8, 0x00, 0x90, 0x9B, 0xF8, + 0x00, 0x20, 0x64, 0x1C, 0xC1, 0x46, 0x08, 0xEB, 0x42, 0x08, 0xE4, 0xB2, 0x28, 0x30, 0xBC, 0x42, + 0xC7, 0xD9, 0x00, 0x20, 0x66, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0x4F, 0xF0, 0x00, 0x0A, 0x89, 0x46, + 0x04, 0x46, 0x01, 0x26, 0x57, 0x46, 0xD0, 0x46, 0x85, 0x78, 0x2A, 0xE0, 0x29, 0x46, 0xD9, 0xF8, + 0x08, 0x00, 0x08, 0xF0, 0x75, 0xFD, 0x02, 0x46, 0x00, 0x20, 0x21, 0x78, 0x63, 0x78, 0x04, 0xE0, + 0x32, 0xF9, 0x11, 0xC0, 0x49, 0x1C, 0x60, 0x44, 0xC9, 0xB2, 0x8B, 0x42, 0xF8, 0xD2, 0xA1, 0x78, + 0x4A, 0x1C, 0xAA, 0x42, 0x10, 0xD2, 0x47, 0x4A, 0x12, 0x68, 0xB2, 0xF8, 0x28, 0x34, 0x03, 0xEB, + 0x08, 0x02, 0xBA, 0x42, 0x01, 0xDA, 0x82, 0x42, 0x33, 0xDB, 0x89, 0x1C, 0xA9, 0x42, 0x03, 0xD2, + 0x52, 0x45, 0x01, 0xDA, 0x82, 0x42, 0x2C, 0xDB, 0xBA, 0x46, 0x47, 0x46, 0x6D, 0x1C, 0x80, 0x46, + 0xED, 0xB2, 0xE0, 0x78, 0xA8, 0x42, 0xD1, 0xD2, 0x00, 0x20, 0x00, 0x90, 0x82, 0x46, 0x83, 0x46, + 0x25, 0x78, 0x2E, 0xE0, 0x4F, 0xF0, 0x00, 0x08, 0xA7, 0x78, 0x09, 0xE0, 0x39, 0x46, 0xD9, 0xF8, + 0x08, 0x00, 0x08, 0xF0, 0x3D, 0xFD, 0x30, 0xF9, 0x15, 0x10, 0x7F, 0x1C, 0x88, 0x44, 0xFF, 0xB2, + 0xE0, 0x78, 0xB8, 0x42, 0xF2, 0xD2, 0x20, 0x78, 0x41, 0x1C, 0xA9, 0x42, 0x13, 0xD2, 0x2D, 0x49, + 0x09, 0x68, 0xB1, 0xF8, 0x28, 0x24, 0x02, 0xEB, 0x0B, 0x01, 0x51, 0x45, 0x03, 0xDA, 0x41, 0x45, + 0x01, 0xDA, 0x00, 0x26, 0x10, 0xE0, 0x80, 0x1C, 0xA8, 0x42, 0x04, 0xD2, 0x00, 0x98, 0x81, 0x42, + 0x01, 0xDA, 0x41, 0x45, 0xF5, 0xDB, 0xCD, 0xF8, 0x00, 0xA0, 0xDA, 0x46, 0x6D, 0x1C, 0xC3, 0x46, + 0xED, 0xB2, 0x60, 0x78, 0xA8, 0x42, 0xCD, 0xD2, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x2D, 0xE9, + 0xF0, 0x41, 0x07, 0x46, 0x98, 0x8C, 0x14, 0x46, 0x00, 0x26, 0x1D, 0x46, 0xC2, 0x05, 0x02, 0xD5, + 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x06, 0x27, 0xD4, 0x16, 0x48, 0xEA, 0x8C, 0x00, 0x68, + 0x90, 0xF8, 0x23, 0x34, 0x9A, 0x42, 0x20, 0xD3, 0xB0, 0xF8, 0x24, 0x34, 0xAA, 0x69, 0x9A, 0x42, + 0x1B, 0xDC, 0x62, 0x78, 0x23, 0x78, 0x90, 0xF8, 0x26, 0x04, 0xD2, 0x1A, 0x52, 0x1C, 0x82, 0x42, + 0x13, 0xDC, 0xE2, 0x78, 0xA3, 0x78, 0xD2, 0x1A, 0x52, 0x1C, 0x82, 0x42, 0x0D, 0xDC, 0x2B, 0x46, + 0x22, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xEF, 0xFE, 0x01, 0x28, 0x06, 0xD1, 0x29, 0x46, 0x20, 0x46, + 0xFF, 0xF7, 0x59, 0xFF, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x26, 0x30, 0x46, 0xD1, 0xE7, 0x00, 0x00, + 0x28, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0xF4, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x70, 0x47, 0xF0, 0xB5, 0x68, 0x4B, 0x02, 0x46, + 0x0C, 0x46, 0x1F, 0x78, 0x67, 0x4B, 0x1E, 0x68, 0x67, 0x4B, 0x1D, 0x78, 0x19, 0xE0, 0x2B, 0x46, + 0x11, 0xE0, 0x00, 0xBF, 0x34, 0xF8, 0x13, 0xC0, 0x32, 0xF8, 0x13, 0xE0, 0xAC, 0xEB, 0x0E, 0x0C, + 0xB6, 0xF9, 0x46, 0xE0, 0x0F, 0xFA, 0x8C, 0xFC, 0x1E, 0xEB, 0x0C, 0x0F, 0x22, 0xD4, 0xB6, 0xF8, + 0x48, 0xE0, 0xE6, 0x45, 0x1E, 0xDB, 0x5B, 0x1E, 0xEC, 0xD1, 0x02, 0xEB, 0x45, 0x02, 0x04, 0xEB, + 0x45, 0x04, 0x7F, 0x1E, 0xE3, 0xD2, 0x96, 0xF8, 0x44, 0x20, 0x58, 0x4B, 0x02, 0xF0, 0x0F, 0x02, + 0xC2, 0xF1, 0x10, 0x04, 0xB3, 0xF9, 0x00, 0x30, 0x0A, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x13, 0x50, + 0x30, 0xF9, 0x13, 0x60, 0x55, 0x43, 0x06, 0xFB, 0x04, 0x55, 0x2D, 0x11, 0x21, 0xF8, 0x13, 0x50, + 0x5B, 0x1E, 0xF3, 0xD2, 0xF0, 0xBD, 0xF0, 0xB5, 0x14, 0x46, 0x05, 0x9F, 0x0B, 0xE0, 0x00, 0xBF, + 0x31, 0xF9, 0x14, 0x50, 0x30, 0xF9, 0x14, 0x60, 0x05, 0xEB, 0x03, 0x0C, 0xB4, 0x45, 0x19, 0xDB, + 0xED, 0x1B, 0xB5, 0x42, 0x16, 0xDC, 0x64, 0x1E, 0xF2, 0xD1, 0x42, 0x4B, 0x1B, 0x68, 0x93, 0xF8, + 0x45, 0x30, 0x1B, 0x09, 0xC3, 0xF1, 0x10, 0x04, 0x0A, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x12, 0x50, + 0x30, 0xF9, 0x12, 0x60, 0x5D, 0x43, 0x06, 0xFB, 0x04, 0x55, 0x2D, 0x11, 0x21, 0xF8, 0x12, 0x50, + 0x52, 0x1E, 0xF3, 0xD2, 0xF0, 0xBD, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x00, 0xF0, 0x6D, 0xFF, + 0x00, 0x28, 0x25, 0xD1, 0xE8, 0x07, 0x08, 0xD0, 0x35, 0x48, 0x36, 0x49, 0x00, 0x78, 0x09, 0x68, + 0x01, 0x28, 0x20, 0x68, 0x1D, 0xD0, 0x00, 0xF0, 0x1F, 0xF8, 0xE8, 0x06, 0x18, 0xD5, 0x2D, 0x4D, + 0x28, 0x68, 0xB0, 0xF9, 0x50, 0x10, 0x00, 0x91, 0x29, 0x49, 0xB0, 0xF9, 0x4E, 0x30, 0x20, 0x69, + 0x0A, 0x78, 0x2D, 0x49, 0xFF, 0xF7, 0xB7, 0xFF, 0x28, 0x68, 0xB0, 0xF9, 0x54, 0x10, 0x00, 0x91, + 0x25, 0x49, 0xB0, 0xF9, 0x52, 0x30, 0x60, 0x69, 0x0A, 0x78, 0x28, 0x49, 0xFF, 0xF7, 0xAB, 0xFF, + 0x38, 0xBD, 0xFF, 0xF7, 0x6A, 0xFF, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x43, 0x81, 0x46, 0x24, 0x48, + 0x03, 0x78, 0x1C, 0x48, 0x05, 0x2B, 0x00, 0x68, 0x90, 0xF8, 0x44, 0x20, 0x0D, 0xD0, 0x30, 0xF9, + 0x46, 0x5F, 0x02, 0xF0, 0x0F, 0x03, 0xB0, 0xF9, 0x02, 0x60, 0x00, 0xBF, 0x17, 0x48, 0xC3, 0xF1, + 0x10, 0x04, 0xB0, 0xF9, 0x00, 0x00, 0x02, 0x46, 0x11, 0xE0, 0x30, 0xF9, 0x4A, 0x5F, 0x13, 0x09, + 0xB0, 0xF9, 0x02, 0x60, 0xF2, 0xE7, 0x00, 0xBF, 0x31, 0xF9, 0x12, 0x70, 0x39, 0xF9, 0x12, 0xC0, + 0x07, 0xEB, 0x05, 0x08, 0xE0, 0x45, 0x11, 0xDB, 0xBF, 0x1B, 0x67, 0x45, 0x0E, 0xDC, 0x52, 0x1E, + 0xF2, 0xD2, 0x09, 0xE0, 0x31, 0xF9, 0x10, 0x20, 0x39, 0xF9, 0x10, 0x50, 0x5A, 0x43, 0x05, 0xFB, + 0x04, 0x22, 0x12, 0x11, 0x21, 0xF8, 0x10, 0x20, 0x40, 0x1E, 0xF3, 0xD2, 0xBD, 0xE8, 0xF0, 0x83, + 0xB9, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, + 0xBF, 0x06, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, + 0xB8, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFC, 0x47, 0x81, 0x46, 0xB9, 0x48, 0xB9, 0x4E, 0x88, 0x46, + 0x01, 0x78, 0x30, 0x68, 0x01, 0x25, 0x11, 0xB9, 0xB7, 0x49, 0x09, 0x78, 0x11, 0xB1, 0xB0, 0xF9, + 0xA1, 0x42, 0x0D, 0xE0, 0xB5, 0x49, 0xB0, 0xF9, 0x9B, 0x42, 0x49, 0x78, 0x01, 0x29, 0x02, 0xD0, + 0x02, 0x29, 0x03, 0xD0, 0x04, 0xE0, 0xB0, 0xF9, 0x9D, 0x42, 0x01, 0xE0, 0xB0, 0xF9, 0x9F, 0x42, + 0x02, 0x21, 0x01, 0xA8, 0x00, 0xF0, 0xBE, 0xFA, 0xAD, 0x4F, 0x42, 0x46, 0x49, 0x46, 0xB7, 0xF9, + 0x00, 0x30, 0x01, 0x98, 0x03, 0xF0, 0xE1, 0xFD, 0x31, 0x68, 0x91, 0xF8, 0xAA, 0x02, 0x02, 0x07, + 0x05, 0xD4, 0xC0, 0x06, 0x03, 0xD4, 0x91, 0xF8, 0xAB, 0x02, 0xC0, 0x07, 0x08, 0xD0, 0xB7, 0xF9, + 0x00, 0x00, 0x01, 0x99, 0x00, 0x90, 0x80, 0x23, 0xA2, 0x4A, 0x08, 0x46, 0x03, 0xF0, 0xDA, 0xFD, + 0xB7, 0xF9, 0x00, 0x10, 0x01, 0x9A, 0x0C, 0xE0, 0x32, 0xF9, 0x11, 0x00, 0x00, 0x28, 0x01, 0xDB, + 0x03, 0x46, 0x00, 0xE0, 0x43, 0x42, 0xA3, 0x42, 0x03, 0xDD, 0x9B, 0x49, 0x00, 0x25, 0x08, 0x80, + 0x01, 0xE0, 0x49, 0x1E, 0xF0, 0xD2, 0x02, 0x21, 0x01, 0xA8, 0x00, 0xF0, 0xEE, 0xFA, 0x28, 0x46, + 0xBD, 0xE8, 0xFC, 0x87, 0x8F, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x90, 0x02, 0x40, 0x07, 0x07, 0xD5, + 0x8E, 0x48, 0x92, 0x49, 0xC0, 0x78, 0x09, 0x78, 0x88, 0x42, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, + 0x00, 0x20, 0x70, 0x47, 0x87, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x90, 0xF8, 0x90, 0x12, 0x89, 0x07, + 0x27, 0xD5, 0x8B, 0x49, 0x0A, 0x78, 0x52, 0x1C, 0xD2, 0xB2, 0x0A, 0x70, 0x90, 0xF8, 0x92, 0x32, + 0x93, 0x42, 0x1E, 0xD2, 0x00, 0x22, 0x0A, 0x70, 0x90, 0xF8, 0x50, 0x12, 0x03, 0x24, 0xC9, 0x07, + 0x03, 0xD1, 0x90, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x0B, 0x24, 0xF1, 0xF7, 0xC6, 0xFF, + 0x80, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF1, 0xF7, 0xBE, 0xFF, 0x10, 0x21, 0x05, 0x20, + 0x02, 0xF0, 0x40, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x06, 0xF0, + 0x32, 0xB9, 0x10, 0xBD, 0x6E, 0x49, 0x70, 0x4A, 0x70, 0x48, 0x09, 0x78, 0x12, 0x78, 0x43, 0x78, + 0x11, 0x43, 0x0B, 0x43, 0x72, 0x49, 0x4F, 0xF0, 0x00, 0x02, 0x08, 0xD1, 0x4B, 0x78, 0x5B, 0x1C, + 0xDB, 0xB2, 0x4B, 0x70, 0x05, 0x2B, 0x03, 0xD9, 0x01, 0x23, 0x43, 0x70, 0x83, 0x70, 0x4A, 0x70, + 0x70, 0x47, 0x2D, 0xE9, 0xF3, 0x4F, 0x6C, 0x48, 0x00, 0x27, 0xDF, 0xF8, 0x94, 0xA1, 0x90, 0xF8, + 0x00, 0x80, 0x60, 0x48, 0x81, 0xB0, 0x8B, 0x46, 0x00, 0x68, 0x3C, 0x46, 0xB9, 0x46, 0x90, 0xF8, + 0x90, 0x02, 0xC0, 0x07, 0x1F, 0xD0, 0x00, 0x26, 0x01, 0x9D, 0x16, 0xE0, 0x63, 0x4A, 0x28, 0x46, + 0x59, 0x46, 0x12, 0x78, 0x01, 0x2A, 0x13, 0xD0, 0xFF, 0xF7, 0x34, 0xFF, 0x10, 0xF0, 0x01, 0x0F, + 0x05, 0xD0, 0x01, 0x20, 0xB0, 0x40, 0x38, 0x43, 0x64, 0x1C, 0xC7, 0xB2, 0xE4, 0xB2, 0xBA, 0xF9, + 0x00, 0x00, 0x76, 0x1C, 0x05, 0xEB, 0x40, 0x05, 0x36, 0xB2, 0x46, 0x45, 0xE6, 0xDB, 0x04, 0xE0, + 0x00, 0xF0, 0x21, 0xF8, 0xEA, 0xE7, 0x44, 0x46, 0xFF, 0x27, 0x55, 0x48, 0x07, 0x70, 0x4C, 0xB1, + 0x00, 0x94, 0xBA, 0xF8, 0x00, 0x00, 0x3B, 0x46, 0x82, 0xB2, 0x41, 0x46, 0x01, 0x98, 0x00, 0xF0, + 0x4A, 0xF8, 0x07, 0xE0, 0x48, 0x48, 0xB0, 0xF9, 0x00, 0x10, 0x03, 0x20, 0x02, 0xF0, 0xDA, 0xF9, + 0x4F, 0xF0, 0x01, 0x09, 0x48, 0x46, 0xBD, 0xE8, 0xFE, 0x8F, 0x70, 0x47, 0x44, 0x48, 0x00, 0x21, + 0x01, 0x70, 0x41, 0x70, 0x70, 0x47, 0x70, 0xB5, 0x39, 0x4A, 0x13, 0x78, 0x39, 0x4A, 0x12, 0x68, + 0x13, 0xB9, 0x39, 0x4B, 0x1B, 0x78, 0x13, 0xB1, 0xB2, 0xF9, 0x99, 0x32, 0x0D, 0xE0, 0x37, 0x4C, + 0xB2, 0xF9, 0x93, 0x32, 0x64, 0x78, 0x01, 0x2C, 0x02, 0xD0, 0x02, 0x2C, 0x03, 0xD0, 0x04, 0xE0, + 0xB2, 0xF9, 0x95, 0x32, 0x01, 0xE0, 0xB2, 0xF9, 0x97, 0x32, 0x31, 0x4A, 0x39, 0x4C, 0xB2, 0xF9, + 0x00, 0x20, 0x25, 0x78, 0x13, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x12, 0x40, 0x31, 0xF9, 0x12, 0x60, + 0xA4, 0x1B, 0x00, 0xD5, 0x64, 0x42, 0x24, 0xB2, 0x9C, 0x42, 0x08, 0xDD, 0x92, 0xFB, 0xF5, 0xF6, + 0x05, 0xFB, 0x16, 0x26, 0x1E, 0xB1, 0x28, 0x48, 0x04, 0x80, 0x00, 0x20, 0x70, 0xBD, 0x52, 0x1E, + 0xEA, 0xD2, 0x01, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x03, 0x06, 0x9F, 0x00, 0x2F, 0x19, 0xD0, + 0x01, 0x25, 0x01, 0x2F, 0x02, 0xD0, 0x14, 0x46, 0xA9, 0x46, 0x2E, 0xE0, 0x00, 0x24, 0x0F, 0xE0, + 0x05, 0xFA, 0x04, 0xF6, 0x1E, 0x42, 0x0A, 0xD0, 0x00, 0x2C, 0x0B, 0xD0, 0x53, 0x00, 0x62, 0x43, + 0xBD, 0xE8, 0xF0, 0x03, 0x00, 0xEB, 0x42, 0x01, 0x1A, 0x46, 0x08, 0xF0, 0x03, 0xB9, 0x64, 0x1C, + 0x8C, 0x42, 0xED, 0xDB, 0xBD, 0xE8, 0xF0, 0x03, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x26, 0x00, 0xEB, + 0x44, 0x0C, 0x35, 0x46, 0x0B, 0xE0, 0x00, 0xBF, 0x09, 0xFA, 0x05, 0xF8, 0x18, 0xEA, 0x03, 0x0F, + 0x02, 0xD0, 0xBC, 0xF9, 0x00, 0x80, 0x46, 0x44, 0x0C, 0xEB, 0x42, 0x0C, 0x6D, 0x1C, 0x8D, 0x42, + 0xF2, 0xDB, 0x96, 0xFB, 0xF7, 0xF5, 0x20, 0xF8, 0x14, 0x50, 0x64, 0x1E, 0xE6, 0xD2, 0xE1, 0xE7, + 0x1C, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0xCA, 0x06, 0x10, 0x00, 0x78, 0x12, 0x01, 0x20, 0x56, 0x06, 0x10, 0x00, 0xBB, 0x06, 0x10, 0x00, + 0x4C, 0x06, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0xBC, 0x06, 0x10, 0x00, 0xBF, 0x06, 0x10, 0x00, + 0x51, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x10, 0xB5, 0xF6, 0xF7, 0x51, 0xFD, 0xF7, 0xF7, + 0xE2, 0xF9, 0xBD, 0xE8, 0x10, 0x40, 0xF5, 0xF7, 0x51, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0x81, 0x46, + 0x1F, 0x46, 0x90, 0x46, 0x0E, 0x46, 0x03, 0x20, 0x08, 0x9D, 0x06, 0xF0, 0xC4, 0xF8, 0x6E, 0x48, + 0x01, 0x68, 0x48, 0x46, 0xFF, 0xF7, 0x05, 0xFF, 0x04, 0x46, 0x03, 0x20, 0x06, 0xF0, 0xD6, 0xF8, + 0x64, 0xB1, 0xFF, 0xF7, 0xE7, 0xFE, 0xFF, 0xF7, 0xB5, 0xFE, 0x31, 0x46, 0x48, 0x46, 0xFF, 0xF7, + 0x44, 0xFF, 0x66, 0x48, 0x04, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xFF, 0xF7, 0x3E, 0xFF, + 0x16, 0xB1, 0x30, 0x46, 0x00, 0xF0, 0xCC, 0xFB, 0x5D, 0xB1, 0x61, 0x48, 0x01, 0x78, 0x28, 0x46, + 0xF6, 0xF7, 0x45, 0xFD, 0x5F, 0x48, 0x80, 0x78, 0x18, 0xB1, 0x5F, 0x49, 0x00, 0x20, 0x08, 0x70, + 0x48, 0x70, 0x08, 0xF0, 0xC3, 0xF9, 0x05, 0x46, 0xFF, 0xF7, 0x84, 0xFE, 0x50, 0xEA, 0x05, 0x04, + 0xDB, 0xD1, 0x3A, 0x46, 0x41, 0x46, 0x48, 0x46, 0x00, 0xF0, 0x3C, 0xF8, 0x04, 0x46, 0xD4, 0xE7, + 0x10, 0xB5, 0x04, 0x46, 0x00, 0xF0, 0x7F, 0xF8, 0x00, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x15, 0xFF, + 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xF8, 0xF7, 0x34, 0xFA, 0xFD, 0xF7, 0xA5, 0xFE, 0xFB, 0xF7, + 0xDF, 0xFC, 0xFF, 0xF7, 0xA1, 0xFF, 0xFF, 0xF7, 0x09, 0xFF, 0xFC, 0xF7, 0x7E, 0xFB, 0x47, 0x49, + 0x00, 0x20, 0x08, 0x70, 0x48, 0x70, 0x88, 0x80, 0xC8, 0x80, 0x88, 0x70, 0x88, 0x60, 0xC8, 0x60, + 0x08, 0x61, 0x14, 0x31, 0x08, 0x70, 0x88, 0x70, 0x44, 0x48, 0x00, 0x68, 0x10, 0xF8, 0x30, 0x2F, + 0x4A, 0x70, 0x40, 0x78, 0xC8, 0x70, 0x10, 0xBD, 0x10, 0xB5, 0xF8, 0xF7, 0x23, 0xFA, 0xFD, 0xF7, + 0x96, 0xFE, 0x00, 0xF0, 0xF0, 0xFB, 0xF7, 0xF7, 0x73, 0xF9, 0x3A, 0x48, 0x00, 0x21, 0x41, 0x70, + 0x81, 0x70, 0x10, 0xBD, 0xF8, 0xB5, 0x07, 0x46, 0x00, 0x24, 0x15, 0x46, 0x0E, 0x46, 0x8D, 0xF8, + 0x00, 0x40, 0x02, 0x20, 0x06, 0xF0, 0x47, 0xF8, 0x2A, 0x46, 0x31, 0x46, 0x38, 0x46, 0xF8, 0xF7, + 0x6A, 0xF8, 0x33, 0x49, 0x01, 0x28, 0xCA, 0x78, 0x60, 0xF3, 0x03, 0x02, 0xCA, 0x70, 0x28, 0xD0, + 0x02, 0x28, 0x2B, 0xD0, 0x04, 0x28, 0x00, 0xD0, 0x01, 0x24, 0x6B, 0x46, 0x2A, 0x46, 0x31, 0x46, + 0x38, 0x46, 0xFC, 0xF7, 0x63, 0xFA, 0x40, 0xEA, 0x04, 0x05, 0x02, 0x20, 0x06, 0xF0, 0x46, 0xF8, + 0x9D, 0xF8, 0x00, 0x00, 0x98, 0xB1, 0xF1, 0xF7, 0x09, 0xFE, 0x26, 0x48, 0x26, 0x4A, 0x01, 0x68, + 0x12, 0x68, 0x11, 0x43, 0x01, 0x60, 0xF1, 0xF7, 0xFF, 0xFD, 0x24, 0x48, 0x01, 0x78, 0x05, 0x20, + 0x02, 0xF0, 0x80, 0xF8, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x05, 0xF0, 0x74, 0xFF, 0x28, 0x46, + 0xF8, 0xBD, 0xFD, 0xF7, 0x2B, 0xFE, 0xFB, 0xF7, 0x94, 0xFC, 0xD6, 0xE7, 0xFD, 0xF7, 0x86, 0xFB, + 0xFB, 0xF7, 0xBC, 0xFC, 0xD1, 0xE7, 0x70, 0xB5, 0x05, 0x46, 0x00, 0x24, 0x02, 0x20, 0x06, 0xF0, + 0x02, 0xF8, 0x28, 0x46, 0xF8, 0xF7, 0x4B, 0xF9, 0x11, 0x49, 0x01, 0x28, 0xCA, 0x78, 0x60, 0xF3, + 0x03, 0x02, 0xCA, 0x70, 0x02, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x08, 0xE0, 0xFD, 0xF7, 0x1B, 0xFE, + 0xFB, 0xF7, 0xEA, 0xFC, 0x03, 0xE0, 0xFD, 0xF7, 0xFA, 0xFC, 0xFB, 0xF7, 0xF6, 0xFC, 0x02, 0x20, + 0x06, 0xF0, 0x04, 0xF8, 0x20, 0x46, 0x70, 0xBD, 0xE8, 0x06, 0x10, 0x00, 0x50, 0x06, 0x10, 0x00, + 0x50, 0x07, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0xE6, 0x43, 0x01, 0x20, 0x28, 0x07, 0x10, 0x00, 0x08, 0x06, 0x10, 0x00, 0x04, 0x06, 0x10, 0x00, + 0x06, 0x29, 0x04, 0xD2, 0x8B, 0x4A, 0x51, 0x5C, 0x8B, 0x4A, 0x53, 0x5C, 0x2B, 0xB1, 0x00, 0x21, + 0x01, 0x60, 0x01, 0x46, 0x48, 0x20, 0x01, 0xF0, 0x02, 0xBD, 0x86, 0x4B, 0x08, 0x33, 0x53, 0xF8, + 0x21, 0x30, 0x03, 0x60, 0x85, 0x4B, 0x43, 0xF8, 0x21, 0x00, 0x01, 0x20, 0x50, 0x54, 0x70, 0x47, + 0x0A, 0x46, 0x30, 0xB4, 0x00, 0x21, 0x06, 0x2A, 0x11, 0xD2, 0x7E, 0x4B, 0x9A, 0x5C, 0x72, 0xB1, + 0x7C, 0x4C, 0x03, 0x68, 0x08, 0x34, 0x54, 0xF8, 0x22, 0x40, 0xA3, 0x42, 0x07, 0xD1, 0x7A, 0x4B, + 0x99, 0x54, 0x7A, 0x4B, 0x43, 0xF8, 0x22, 0x10, 0x01, 0x60, 0x30, 0xBC, 0x70, 0x47, 0x01, 0x60, + 0x01, 0x46, 0x30, 0xBC, 0x49, 0x20, 0x01, 0xF0, 0xDA, 0xBC, 0x2D, 0xE9, 0xF0, 0x41, 0x01, 0x24, + 0x71, 0x4D, 0x72, 0x4F, 0x00, 0x26, 0x28, 0x5D, 0x38, 0xB1, 0x2E, 0x55, 0x57, 0xF8, 0x24, 0x10, + 0x4A, 0x20, 0x01, 0xF0, 0xCC, 0xFC, 0x47, 0xF8, 0x24, 0x60, 0x64, 0x1C, 0x03, 0x2C, 0xF2, 0xDB, + 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x41, 0x68, 0x4D, 0x67, 0x4B, 0x00, 0x27, 0x0A, 0x46, + 0x0C, 0x35, 0x07, 0x60, 0x59, 0x68, 0x05, 0xF1, 0x14, 0x06, 0x03, 0xF1, 0x08, 0x04, 0x01, 0x2A, + 0x38, 0xD0, 0x02, 0x2A, 0x1C, 0xD0, 0x03, 0x2A, 0x3F, 0xD1, 0x00, 0x22, 0x04, 0xEB, 0x02, 0x0C, + 0xDC, 0xF8, 0x00, 0xE0, 0xBE, 0xF1, 0x00, 0x0F, 0x07, 0xD0, 0x52, 0x1C, 0x02, 0x2A, 0xF5, 0xDB, + 0x04, 0x29, 0x30, 0xD3, 0x01, 0x46, 0x4C, 0x20, 0x31, 0xE0, 0x55, 0xF8, 0x22, 0x40, 0x04, 0x60, + 0x46, 0xF8, 0x22, 0x00, 0x4F, 0xF0, 0x03, 0x30, 0x09, 0x1F, 0xCC, 0xF8, 0x00, 0x00, 0x32, 0xE0, + 0x5F, 0xF0, 0x00, 0x02, 0x04, 0xEB, 0x02, 0x0C, 0xBC, 0xF8, 0x00, 0xE0, 0xBE, 0xF1, 0x00, 0x0F, + 0x05, 0xD0, 0x52, 0x1C, 0x04, 0x2A, 0xF5, 0xDB, 0x02, 0x29, 0xE3, 0xD2, 0x13, 0xE0, 0x55, 0xF8, + 0x22, 0x40, 0x04, 0x60, 0x46, 0xF8, 0x22, 0x00, 0x40, 0xF2, 0x02, 0x20, 0xAC, 0xF8, 0x00, 0x00, + 0x89, 0x1E, 0x18, 0xE0, 0x5F, 0xF0, 0x04, 0x02, 0x14, 0xF8, 0x02, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, + 0x09, 0xD0, 0x52, 0x1E, 0xF8, 0xD2, 0x00, 0x2F, 0xAA, 0xD1, 0x01, 0x46, 0x4B, 0x20, 0xBD, 0xE8, + 0xF0, 0x41, 0x01, 0xF0, 0x6C, 0xBC, 0x55, 0xF8, 0x22, 0x50, 0x05, 0x60, 0x46, 0xF8, 0x22, 0x00, + 0x01, 0x20, 0xA0, 0x54, 0x49, 0x1E, 0x59, 0x60, 0x9A, 0xE7, 0xF0, 0xB4, 0x37, 0x4E, 0x36, 0x4C, + 0x00, 0x25, 0x04, 0x22, 0x0C, 0x36, 0xD0, 0xF8, 0x00, 0x30, 0x08, 0x34, 0x56, 0xF8, 0x22, 0x70, + 0x9F, 0x42, 0x12, 0xD1, 0xA7, 0x5C, 0x8F, 0x42, 0x0F, 0xD1, 0x53, 0x1C, 0x11, 0xD0, 0x2F, 0x4D, + 0x00, 0x23, 0x20, 0x35, 0x03, 0x60, 0x45, 0xF8, 0x22, 0x30, 0xA3, 0x54, 0x01, 0x29, 0x11, 0xD0, + 0x02, 0x29, 0x11, 0xD0, 0x03, 0x29, 0x04, 0xD1, 0x08, 0xE0, 0x52, 0x1E, 0xE6, 0xD2, 0x00, 0x2D, + 0x08, 0xD1, 0xF0, 0xBC, 0x01, 0x46, 0x4D, 0x20, 0x01, 0xF0, 0x39, 0xBC, 0xA0, 0x18, 0x43, 0x70, + 0x83, 0x70, 0xC3, 0x70, 0xF0, 0xBC, 0x70, 0x47, 0xA0, 0x18, 0x43, 0x70, 0xFA, 0xE7, 0x70, 0xB5, + 0x1D, 0x4E, 0x1E, 0x4D, 0x05, 0x24, 0x08, 0x36, 0x20, 0x35, 0x0B, 0xE0, 0x30, 0x5D, 0x48, 0xB1, + 0x55, 0xF8, 0x24, 0x10, 0x4E, 0x20, 0x01, 0xF0, 0x22, 0xFC, 0x31, 0x5D, 0x55, 0xF8, 0x24, 0x00, + 0xFF, 0xF7, 0xBB, 0xFF, 0x64, 0x1E, 0xF1, 0xD2, 0x70, 0xBD, 0x70, 0xB5, 0x01, 0x20, 0x13, 0x4B, + 0x11, 0x4A, 0x00, 0x21, 0x43, 0xF8, 0x20, 0x10, 0x11, 0x54, 0x40, 0x1C, 0x03, 0x28, 0xF9, 0xDB, + 0x01, 0x20, 0x10, 0x70, 0x0C, 0x4A, 0x05, 0x20, 0x0C, 0x4B, 0x50, 0x60, 0x0C, 0x33, 0x0A, 0x4C, + 0x04, 0x20, 0x0B, 0x4A, 0x08, 0x34, 0x03, 0xF1, 0x14, 0x05, 0x73, 0x26, 0x46, 0x43, 0x02, 0xEB, + 0xC6, 0x06, 0x43, 0xF8, 0x20, 0x60, 0x21, 0x54, 0x45, 0xF8, 0x20, 0x10, 0x40, 0x1E, 0xF4, 0xD2, + 0x70, 0xBD, 0x00, 0x00, 0x58, 0x6C, 0x01, 0x00, 0x8C, 0x06, 0x10, 0x00, 0x88, 0x47, 0x10, 0x00, + 0x84, 0x5A, 0x10, 0x00, 0xF0, 0xB5, 0x06, 0x46, 0xF8, 0x48, 0x00, 0x24, 0xA7, 0xB0, 0x00, 0x78, + 0x0D, 0x46, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x98, 0x21, 0x68, 0x46, 0x07, 0xF0, 0x33, 0xFF, + 0xF3, 0x4A, 0x00, 0x21, 0x68, 0x46, 0x13, 0x78, 0x11, 0xE0, 0x00, 0xBF, 0x01, 0xFB, 0x03, 0xF7, + 0x22, 0x46, 0x09, 0xE0, 0x07, 0xEB, 0x02, 0x0E, 0x50, 0xF8, 0x22, 0xC0, 0x36, 0xF9, 0x1E, 0xE0, + 0xF4, 0x44, 0x40, 0xF8, 0x22, 0xC0, 0x52, 0x1C, 0x9A, 0x42, 0xF3, 0xDB, 0x49, 0x1C, 0xA9, 0x42, + 0xEC, 0xDB, 0x21, 0x46, 0x07, 0xE0, 0x00, 0xBF, 0x50, 0xF8, 0x21, 0x20, 0x92, 0xFB, 0xF5, 0xF2, + 0x40, 0xF8, 0x21, 0x20, 0x49, 0x1C, 0x99, 0x42, 0xF6, 0xDB, 0x00, 0x21, 0x17, 0xE0, 0x00, 0x27, + 0x3A, 0x46, 0x0C, 0xE0, 0x02, 0xFB, 0x03, 0x4C, 0x50, 0xF8, 0x24, 0xE0, 0x36, 0xF9, 0x1C, 0xC0, + 0xBC, 0xEB, 0x0E, 0x0C, 0x01, 0xD5, 0xCC, 0xF1, 0x00, 0x0C, 0x67, 0x44, 0x52, 0x1C, 0xAA, 0x42, + 0xF0, 0xDB, 0x97, 0xFB, 0xF5, 0xF2, 0x8A, 0x42, 0x00, 0xDD, 0x11, 0x46, 0x64, 0x1C, 0x9C, 0x42, + 0xE5, 0xDB, 0xB1, 0xF5, 0x80, 0x3F, 0x03, 0xDB, 0x4F, 0xF6, 0xFF, 0x70, 0x27, 0xB0, 0xF0, 0xBD, + 0x88, 0xB2, 0xFB, 0xE7, 0xF0, 0xB5, 0xCF, 0x49, 0xCF, 0x4B, 0x09, 0x68, 0x91, 0xF8, 0xAA, 0x22, + 0xD2, 0x07, 0x34, 0xD0, 0xCD, 0x4A, 0x57, 0x78, 0x4F, 0xB1, 0x91, 0xF8, 0xB5, 0x42, 0xB1, 0xF8, + 0xB2, 0x52, 0x04, 0xF0, 0x0F, 0x02, 0x26, 0x09, 0xB1, 0xF8, 0xB0, 0x42, 0x08, 0xE0, 0x91, 0xF8, + 0xB4, 0x42, 0xB1, 0xF8, 0xAE, 0x52, 0x04, 0xF0, 0x0F, 0x02, 0x26, 0x09, 0xB1, 0xF8, 0xAC, 0x42, + 0xDF, 0xF8, 0x0C, 0xC3, 0x9C, 0xF8, 0x00, 0xC0, 0xBC, 0xF1, 0x03, 0x0F, 0x06, 0xD1, 0x91, 0xF8, + 0xB6, 0x12, 0x0F, 0xB1, 0x0A, 0x09, 0x01, 0xE0, 0x01, 0xF0, 0x0F, 0x02, 0xA0, 0x42, 0x01, 0xDC, + 0x1A, 0x60, 0xF0, 0xBD, 0xA8, 0x42, 0x01, 0xDB, 0x1E, 0x60, 0xF0, 0xBD, 0x00, 0x1B, 0xB1, 0x1A, + 0x48, 0x43, 0x29, 0x1B, 0x90, 0xFB, 0xF1, 0xF0, 0x10, 0x44, 0x18, 0x60, 0xF0, 0xBD, 0x00, 0x20, + 0xFB, 0xE7, 0xB0, 0x48, 0xB1, 0x49, 0x00, 0x68, 0x0A, 0x78, 0x00, 0xF5, 0xF9, 0x70, 0x80, 0x5C, + 0xC8, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x0F, 0x83, 0x46, 0xAA, 0x48, 0xDF, 0xF8, 0xAC, 0x92, + 0xDF, 0xF8, 0xB0, 0xA2, 0x01, 0x68, 0x99, 0xF8, 0x00, 0x70, 0x00, 0x20, 0x91, 0xF8, 0x0A, 0x62, + 0x91, 0xF8, 0x09, 0x12, 0x3A, 0xF8, 0x17, 0x40, 0x6F, 0xF0, 0x00, 0x42, 0x4F, 0xEA, 0x11, 0x18, + 0x0B, 0x07, 0x1C, 0xD0, 0x01, 0xF0, 0x0F, 0x05, 0x9E, 0x4B, 0x00, 0x21, 0x8C, 0x46, 0x1B, 0x68, + 0xB4, 0x42, 0x93, 0xF8, 0x08, 0x32, 0x05, 0xDB, 0xA6, 0x1B, 0x06, 0xFB, 0x08, 0xF6, 0x96, 0xFB, + 0xF5, 0xF5, 0x2B, 0x44, 0x97, 0x4D, 0x99, 0xF8, 0x01, 0x60, 0x2D, 0x68, 0x01, 0x2E, 0x95, 0xF8, + 0xF1, 0x51, 0x06, 0xD0, 0x02, 0x2E, 0x07, 0xD0, 0x05, 0xF0, 0x03, 0x06, 0x13, 0xE0, 0x01, 0x25, + 0xE2, 0xE7, 0xC5, 0xF3, 0x81, 0x06, 0x0E, 0xE0, 0xC5, 0xF3, 0x01, 0x16, 0x0B, 0xE0, 0x00, 0xBF, + 0x3A, 0xF8, 0x1C, 0x50, 0xAA, 0x42, 0x01, 0xDD, 0x2A, 0x46, 0x60, 0x46, 0xA9, 0x42, 0x00, 0xDA, + 0x29, 0x46, 0x0C, 0xF1, 0x01, 0x0C, 0xB4, 0x45, 0xF2, 0xDD, 0xAB, 0xF8, 0x00, 0x10, 0xA1, 0x1A, + 0x99, 0x42, 0x01, 0xDC, 0xB7, 0x42, 0x04, 0xDD, 0x89, 0xF8, 0x00, 0x00, 0xBD, 0xE8, 0xF0, 0x0F, + 0x9F, 0xE7, 0xBD, 0xE8, 0xF0, 0x0F, 0x70, 0x47, 0x83, 0x49, 0x10, 0xB5, 0x0B, 0x78, 0x7D, 0x49, + 0x00, 0x22, 0x01, 0x2B, 0x09, 0x68, 0x02, 0xD1, 0x80, 0x4B, 0x1B, 0x78, 0x4B, 0xB1, 0xB1, 0xF8, + 0xFC, 0x31, 0x83, 0x42, 0x18, 0xD2, 0x91, 0xF8, 0xF0, 0x31, 0x1B, 0x07, 0x14, 0xD5, 0x03, 0x22, + 0x25, 0xE0, 0xB1, 0xF8, 0x02, 0x32, 0x83, 0x42, 0x03, 0xD2, 0x91, 0xF8, 0xF0, 0x31, 0x1B, 0x07, + 0xF5, 0xD4, 0xB1, 0xF8, 0x00, 0x32, 0x83, 0x42, 0x03, 0xD2, 0x91, 0xF8, 0xF0, 0x31, 0x5B, 0x07, + 0x0A, 0xD4, 0xB1, 0xF8, 0xFE, 0x31, 0x0B, 0xE0, 0xB1, 0xF8, 0xFA, 0x31, 0x83, 0x42, 0x05, 0xD2, + 0x91, 0xF8, 0xF0, 0x31, 0x5B, 0x07, 0x01, 0xD5, 0x02, 0x22, 0x08, 0xE0, 0xB1, 0xF8, 0xF8, 0x31, + 0x83, 0x42, 0x04, 0xD2, 0x91, 0xF8, 0xF0, 0x01, 0x80, 0x07, 0x00, 0xD5, 0x01, 0x22, 0x65, 0x48, + 0x62, 0x4C, 0x14, 0x38, 0x03, 0x78, 0x9A, 0x42, 0x11, 0xD1, 0x61, 0x78, 0x99, 0x42, 0x1A, 0xD0, + 0x63, 0x4A, 0x12, 0x78, 0x13, 0x43, 0x07, 0xD0, 0x81, 0x68, 0x49, 0x1E, 0x81, 0x60, 0x00, 0x29, + 0x11, 0xDC, 0x00, 0x78, 0x60, 0x70, 0x0E, 0xE0, 0x01, 0x70, 0x81, 0x68, 0xF7, 0xE7, 0x8A, 0xB1, + 0x02, 0x2A, 0x01, 0xD1, 0x01, 0x2B, 0x0D, 0xD0, 0x91, 0xF8, 0xF6, 0x11, 0x81, 0x60, 0x02, 0x70, + 0x00, 0x29, 0x00, 0xDC, 0x62, 0x70, 0x57, 0x48, 0x62, 0x78, 0x41, 0x7B, 0x62, 0xF3, 0x03, 0x01, + 0x41, 0x73, 0x10, 0xBD, 0x91, 0xF8, 0xF7, 0x11, 0xF0, 0xE7, 0x4A, 0x4A, 0x12, 0x68, 0x92, 0xF8, + 0xF0, 0x21, 0xD2, 0x06, 0x07, 0xD5, 0x42, 0x1A, 0x00, 0x2A, 0x04, 0xDC, 0xC1, 0xEB, 0xC1, 0x11, + 0x08, 0x44, 0xC0, 0xF3, 0xCF, 0x10, 0x70, 0x47, 0x44, 0x49, 0x00, 0x20, 0x41, 0x4A, 0x48, 0x70, + 0x44, 0x49, 0x14, 0x39, 0x48, 0x60, 0x88, 0x60, 0x08, 0x70, 0x12, 0x68, 0x92, 0xF8, 0xAA, 0x32, + 0xDB, 0x07, 0x03, 0xD0, 0x92, 0xF8, 0xB5, 0x22, 0x12, 0x09, 0x00, 0xE0, 0x00, 0x22, 0x3A, 0x4B, + 0x1A, 0x60, 0xC8, 0x60, 0x08, 0x61, 0x48, 0x61, 0x88, 0x61, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, + 0x00, 0x21, 0xAD, 0xF8, 0x00, 0x10, 0x32, 0x49, 0xDF, 0xF8, 0xD8, 0x90, 0xDF, 0xF8, 0xD4, 0x80, + 0x0E, 0x78, 0x4F, 0xF0, 0x10, 0x0B, 0x37, 0x01, 0x05, 0x46, 0x00, 0x24, 0xA9, 0xF1, 0x08, 0x09, + 0xA8, 0xF1, 0x14, 0x0A, 0x10, 0xE0, 0x32, 0x46, 0x59, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x5A, 0xFE, + 0x29, 0xF8, 0x14, 0x00, 0x43, 0x46, 0x38, 0xF8, 0x14, 0x10, 0xFF, 0xF7, 0xB6, 0xFF, 0x23, 0xF8, + 0x14, 0x00, 0x05, 0xEB, 0x47, 0x05, 0x64, 0x1C, 0x9A, 0xF8, 0x01, 0x00, 0x84, 0x42, 0xEA, 0xDD, + 0x68, 0x46, 0xFF, 0xF7, 0xE7, 0xFE, 0x1F, 0x48, 0x20, 0x4D, 0x00, 0x68, 0x90, 0xF8, 0xF0, 0x01, + 0x40, 0x06, 0x02, 0xD5, 0xBD, 0xF8, 0x00, 0x40, 0x02, 0xE0, 0x29, 0x78, 0x38, 0xF8, 0x11, 0x40, + 0x21, 0x48, 0x04, 0x80, 0x20, 0x46, 0xFF, 0xF7, 0x2F, 0xFF, 0x20, 0x46, 0xFF, 0xF7, 0x8A, 0xFE, + 0x29, 0x78, 0x39, 0xF8, 0x11, 0x00, 0x1B, 0x49, 0xA1, 0xF8, 0x1B, 0x00, 0xBD, 0xE8, 0xF8, 0x8F, + 0x2D, 0xE9, 0xFC, 0x5F, 0x0E, 0x49, 0x4F, 0xF0, 0x00, 0x09, 0x0D, 0x78, 0x0B, 0x49, 0x09, 0x78, + 0x01, 0x29, 0x00, 0xD1, 0x89, 0x46, 0x0F, 0x49, 0x10, 0x26, 0x14, 0x39, 0x04, 0x46, 0x4A, 0x68, + 0x12, 0x48, 0x92, 0xFB, 0xF6, 0xF3, 0x06, 0xFB, 0x13, 0x22, 0x6A, 0x43, 0x4F, 0x78, 0x4F, 0xEA, + 0x05, 0x1A, 0x00, 0xEB, 0x42, 0x08, 0x83, 0x46, 0x7F, 0x1C, 0x3D, 0xE0, 0xBF, 0x06, 0x10, 0x00, + 0xBA, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0xB8, 0x06, 0x10, 0x00, 0xB0, 0x06, 0x10, 0x00, 0xC2, 0x06, 0x10, 0x00, 0xC3, 0x06, 0x10, 0x00, + 0xC1, 0x06, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x54, 0x06, 0x10, 0x00, 0x8C, 0x1C, 0x01, 0x20, + 0x2A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xF0, 0x11, 0x89, 0x06, 0x14, 0xD5, 0x28, 0x49, 0x49, 0x68, + 0x00, 0x29, 0x0E, 0xDD, 0xA5, 0xEB, 0x09, 0x02, 0xB0, 0xF9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, + 0xB0, 0xF9, 0x04, 0x32, 0x04, 0xEB, 0x49, 0x00, 0x0B, 0xEB, 0x49, 0x02, 0x01, 0x46, 0x02, 0xF0, + 0xB3, 0xFF, 0x0B, 0xEB, 0x4A, 0x0B, 0x6A, 0x00, 0x21, 0x46, 0x40, 0x46, 0x07, 0xF0, 0x72, 0xFC, + 0x04, 0xEB, 0x45, 0x04, 0x08, 0xEB, 0x4A, 0x08, 0x7F, 0x1E, 0xD9, 0xD2, 0x18, 0x48, 0x4F, 0xF0, + 0xFF, 0x31, 0x01, 0xEB, 0x46, 0x01, 0x42, 0x68, 0x52, 0x1C, 0x42, 0x60, 0x91, 0x42, 0x00, 0xDA, + 0x46, 0x60, 0x40, 0x68, 0xB0, 0x42, 0x03, 0xDB, 0xBD, 0xE8, 0xFC, 0x5F, 0x11, 0x48, 0x45, 0xE7, + 0xBD, 0xE8, 0xFC, 0x9F, 0x28, 0xE7, 0x10, 0xB5, 0x0C, 0x4C, 0x20, 0x68, 0x90, 0xF8, 0xF1, 0x01, + 0xC0, 0xF3, 0x01, 0x12, 0xC0, 0xF3, 0x81, 0x01, 0x00, 0xF0, 0x03, 0x00, 0x02, 0xF0, 0x73, 0xF9, + 0x07, 0x49, 0x48, 0x70, 0x20, 0x68, 0x08, 0x49, 0x90, 0xF8, 0xEC, 0x00, 0x00, 0xF0, 0x03, 0x00, + 0x08, 0x70, 0xFF, 0xF7, 0x36, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x0D, 0xE7, 0x20, 0x07, 0x10, 0x00, + 0x9C, 0x06, 0x10, 0x00, 0x8C, 0x1C, 0x01, 0x20, 0x4C, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xD1, 0x48, + 0x00, 0x24, 0x84, 0x61, 0x44, 0x63, 0x04, 0x87, 0x80, 0xF8, 0x3A, 0x40, 0x04, 0x62, 0xC4, 0x61, + 0xFF, 0xF7, 0xDA, 0xFB, 0xFF, 0xF7, 0x59, 0xFD, 0xCB, 0x48, 0x04, 0x80, 0xBD, 0xE8, 0x10, 0x40, + 0x00, 0xF0, 0xED, 0xB8, 0xC9, 0x48, 0x10, 0xB5, 0x90, 0xF8, 0x2C, 0x10, 0xC6, 0x48, 0xC5, 0x4A, + 0x81, 0x70, 0x53, 0x7A, 0x01, 0x79, 0x63, 0xF3, 0x00, 0x01, 0xD3, 0x7A, 0x63, 0xF3, 0xC3, 0x01, + 0x93, 0x7A, 0x63, 0xF3, 0x82, 0x01, 0x13, 0x7B, 0x63, 0xF3, 0x41, 0x01, 0xC0, 0x4B, 0xDB, 0x78, + 0x03, 0x72, 0x93, 0x7B, 0xC3, 0x71, 0x53, 0x7B, 0xD4, 0x7B, 0x63, 0xF3, 0x04, 0x11, 0x83, 0x7B, + 0x12, 0x7C, 0x64, 0xF3, 0x03, 0x03, 0x62, 0xF3, 0x07, 0x13, 0xBA, 0x4A, 0x83, 0x73, 0x12, 0x78, + 0x80, 0xF8, 0x28, 0x20, 0xB8, 0x4A, 0x12, 0x88, 0xA0, 0xF8, 0x29, 0x20, 0xB7, 0x4A, 0x12, 0x78, + 0x62, 0xF3, 0x45, 0x11, 0xB6, 0x4A, 0x12, 0x78, 0x62, 0xF3, 0xC7, 0x11, 0x01, 0x71, 0xB5, 0x49, + 0x09, 0x88, 0xA0, 0xF8, 0x2B, 0x10, 0xB4, 0x49, 0x09, 0x88, 0xA0, 0xF8, 0x2D, 0x10, 0xB3, 0x49, + 0x0A, 0x78, 0xC1, 0x7B, 0x62, 0xF3, 0x03, 0x01, 0xC1, 0x73, 0xB1, 0x49, 0x0A, 0x78, 0x01, 0x7C, + 0x62, 0xF3, 0x00, 0x01, 0xAF, 0x4A, 0x12, 0x78, 0x62, 0xF3, 0x41, 0x01, 0xAE, 0x4A, 0x12, 0x78, + 0x62, 0xF3, 0xC3, 0x01, 0x21, 0xF0, 0x04, 0x01, 0x01, 0x74, 0xAC, 0x49, 0x0A, 0x88, 0x02, 0x87, + 0x4A, 0x88, 0x42, 0x87, 0x8A, 0x88, 0x82, 0x87, 0xC9, 0x88, 0xC1, 0x87, 0x10, 0xBD, 0x70, 0xB5, + 0x0D, 0x46, 0x80, 0xEA, 0x05, 0x06, 0xF0, 0x06, 0x01, 0xD5, 0xF6, 0xF7, 0xDC, 0xFC, 0x95, 0x4C, + 0xC5, 0xF3, 0x00, 0x10, 0x34, 0x34, 0x20, 0x70, 0xB0, 0x06, 0x01, 0xD5, 0xF5, 0xF7, 0x46, 0xFA, + 0xC5, 0xF3, 0x40, 0x10, 0x60, 0x70, 0x15, 0xF0, 0x48, 0x00, 0x00, 0xD0, 0x01, 0x20, 0xA0, 0x71, + 0x9B, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x40, 0x14, 0x01, 0xF0, 0x01, 0x01, 0x21, 0x71, 0x90, 0xF8, + 0x20, 0x04, 0x00, 0xF0, 0x01, 0x00, 0x60, 0x71, 0x70, 0xBD, 0x70, 0xB5, 0x85, 0x4D, 0x87, 0x4C, + 0x29, 0x6A, 0x20, 0x6A, 0x81, 0xEA, 0x00, 0x06, 0x19, 0xB9, 0x10, 0xB1, 0xFF, 0xF7, 0x5E, 0xFF, + 0x09, 0xE0, 0xF0, 0x07, 0x03, 0xD0, 0xFF, 0xF7, 0x1D, 0xFB, 0xFF, 0xF7, 0x33, 0xFF, 0xF0, 0x06, + 0x01, 0xD5, 0xFF, 0xF7, 0xC1, 0xFA, 0xE1, 0x69, 0xA8, 0x69, 0xFF, 0xF7, 0xC0, 0xFF, 0xE0, 0x69, + 0xA8, 0x61, 0x20, 0x6A, 0x28, 0x62, 0x60, 0x6A, 0xE8, 0x61, 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, + 0x66, 0xB8, 0x70, 0xB5, 0x83, 0x4D, 0x2C, 0x68, 0x00, 0x2C, 0x0D, 0xD0, 0x71, 0x49, 0xA0, 0xB2, + 0x0A, 0x7A, 0xC9, 0x79, 0x01, 0xF0, 0x1F, 0xFA, 0x28, 0x68, 0xA0, 0x43, 0x28, 0x60, 0x03, 0xD1, + 0xBD, 0xE8, 0x70, 0x40, 0x01, 0xF0, 0x7C, 0xBA, 0x70, 0xBD, 0x6A, 0x48, 0x81, 0x7A, 0x01, 0x29, + 0x08, 0xD0, 0xC1, 0x7A, 0x01, 0x29, 0x05, 0xD0, 0x01, 0x7B, 0x01, 0x29, 0x02, 0xD0, 0x80, 0x7B, + 0x00, 0x28, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x08, 0xB5, 0xFF, 0xF7, 0x1F, 0xFF, 0x6B, 0x46, + 0x00, 0x22, 0x0B, 0x21, 0x02, 0x20, 0x05, 0xF0, 0x07, 0xFB, 0x00, 0x98, 0xC0, 0x07, 0x05, 0xD0, + 0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0xE3, 0xFA, 0x00, 0xF0, 0x56, 0xF8, 0x00, 0x98, 0x80, 0x07, + 0x05, 0xD5, 0x02, 0x21, 0x08, 0x46, 0x05, 0xF0, 0xDA, 0xFA, 0x00, 0xF0, 0x7E, 0xF8, 0x00, 0x98, + 0x00, 0x07, 0xE4, 0xD5, 0x08, 0x21, 0x02, 0x20, 0x05, 0xF0, 0xD1, 0xFA, 0xDF, 0xE7, 0x60, 0x48, + 0x10, 0xB5, 0x02, 0x68, 0x4F, 0x48, 0x92, 0xF8, 0x31, 0x10, 0x41, 0x70, 0x92, 0xF8, 0x30, 0x20, + 0x82, 0x70, 0x51, 0x43, 0x41, 0x82, 0x4E, 0x49, 0xC9, 0x78, 0xC1, 0x70, 0x01, 0x21, 0x01, 0x71, + 0x41, 0x71, 0x81, 0x71, 0x01, 0x70, 0x00, 0x21, 0x81, 0x82, 0xC1, 0x71, 0x01, 0x72, 0xC1, 0x73, + 0x01, 0x74, 0xFF, 0xF7, 0xA7, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0xD5, 0xBF, 0x43, 0x49, + 0x40, 0x48, 0x91, 0xF8, 0x30, 0x20, 0x42, 0x70, 0x91, 0xF8, 0x31, 0x30, 0x83, 0x70, 0x5A, 0x43, + 0x42, 0x82, 0x91, 0xF8, 0x33, 0x20, 0xC2, 0x70, 0x11, 0xF8, 0x2C, 0x2F, 0x02, 0x70, 0x4A, 0x78, + 0x02, 0x71, 0x8A, 0x78, 0x42, 0x71, 0xCA, 0x78, 0x82, 0x71, 0x4A, 0x7A, 0xC2, 0x71, 0x89, 0x7A, + 0x01, 0x72, 0x45, 0x49, 0x41, 0x62, 0x01, 0xF2, 0x3C, 0x61, 0x81, 0x62, 0xA1, 0xF6, 0x78, 0x41, + 0xC1, 0x62, 0x42, 0x49, 0x01, 0x63, 0x70, 0x47, 0x38, 0xB5, 0x00, 0x24, 0x01, 0xF0, 0x10, 0xF8, + 0x01, 0x20, 0x05, 0xF0, 0xF8, 0xFA, 0xFF, 0xF7, 0x48, 0xFF, 0x2A, 0x4D, 0x95, 0xF8, 0x20, 0x00, + 0xC0, 0x07, 0x08, 0xD0, 0x29, 0x48, 0xC1, 0x68, 0x00, 0x91, 0xD0, 0xE9, 0x04, 0x23, 0x03, 0xC8, + 0xFF, 0xF7, 0x1B, 0xFA, 0x04, 0x46, 0xE8, 0x69, 0x50, 0xB1, 0x4C, 0xB9, 0x03, 0x20, 0x05, 0xF0, + 0xE2, 0xFA, 0x22, 0x48, 0xE9, 0x69, 0xFE, 0xF7, 0xF6, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0xF6, 0xFA, + 0xFF, 0xF7, 0xA8, 0xFE, 0xFF, 0xF7, 0x4D, 0xFF, 0xFF, 0xF7, 0xE1, 0xFB, 0xFF, 0xF7, 0x35, 0xFB, + 0xBD, 0xE8, 0x38, 0x40, 0x01, 0x20, 0x05, 0xF0, 0xE9, 0xBA, 0x70, 0xB5, 0x00, 0x24, 0x00, 0xF0, + 0xDF, 0xFF, 0x01, 0x20, 0x05, 0xF0, 0xC7, 0xFA, 0xFF, 0xF7, 0x17, 0xFF, 0x11, 0x4D, 0x95, 0xF8, + 0x20, 0x00, 0xC0, 0x07, 0x04, 0xD0, 0x11, 0x48, 0x00, 0x68, 0xFF, 0xF7, 0x31, 0xFA, 0x04, 0x46, + 0xE8, 0x69, 0x50, 0xB1, 0x4C, 0xB9, 0x03, 0x20, 0x05, 0xF0, 0xB5, 0xFA, 0x0B, 0x48, 0xE9, 0x69, + 0xFE, 0xF7, 0xC9, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0xC9, 0xFA, 0xFF, 0xF7, 0x7B, 0xFE, 0xFF, 0xF7, + 0x20, 0xFF, 0xFF, 0xF7, 0xB4, 0xFB, 0xFF, 0xF7, 0x08, 0xFB, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, + 0x05, 0xF0, 0xBC, 0xBA, 0xB8, 0x06, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x7C, 0x6C, 0x10, 0x00, + 0x4C, 0x07, 0x10, 0x00, 0x51, 0x06, 0x10, 0x00, 0x56, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, + 0x52, 0x07, 0x10, 0x00, 0x54, 0x07, 0x10, 0x00, 0x56, 0x07, 0x10, 0x00, 0x0E, 0x05, 0x10, 0x00, + 0x0C, 0x05, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x21, 0x05, 0x10, 0x00, 0xB0, 0x06, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x40, 0x07, 0x10, 0x00, 0xC8, 0x35, 0x01, 0x20, 0x2E, 0x44, 0x01, 0x20, + 0x0D, 0x4D, 0x00, 0x20, 0x0D, 0x4C, 0x28, 0x60, 0x28, 0x68, 0x40, 0x1C, 0x28, 0x60, 0xF1, 0xF7, + 0x55, 0xF8, 0x07, 0xF0, 0x20, 0xF9, 0x01, 0x28, 0x20, 0x68, 0x09, 0xD0, 0x40, 0xF0, 0x04, 0x00, + 0x20, 0x60, 0x05, 0xF0, 0x6C, 0xFF, 0x00, 0xBF, 0xF1, 0xF7, 0x46, 0xF8, 0x30, 0xBF, 0xEB, 0xE7, + 0x20, 0xF0, 0x04, 0x00, 0x20, 0x60, 0xF7, 0xE7, 0xFC, 0x06, 0x10, 0x00, 0x10, 0xED, 0x00, 0xE0, + 0x2D, 0xE9, 0xF0, 0x47, 0x1C, 0x4D, 0xDF, 0xF8, 0x74, 0x90, 0xA8, 0x46, 0x20, 0x21, 0x1A, 0x48, + 0x07, 0xF0, 0xBF, 0xFA, 0x18, 0x48, 0x00, 0xF0, 0xE9, 0xFB, 0x47, 0x1E, 0xD9, 0xF8, 0x00, 0x00, + 0x98, 0xF8, 0x00, 0x60, 0x08, 0xF1, 0x01, 0x04, 0x90, 0xF8, 0xA0, 0x00, 0xC0, 0x07, 0x05, 0xD0, + 0x3A, 0x46, 0x21, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x23, 0xF8, 0x28, 0xB9, 0x3A, 0x46, 0x21, 0x46, + 0x30, 0x46, 0x00, 0xF0, 0xEB, 0xF8, 0x18, 0xB1, 0x01, 0x20, 0x29, 0x68, 0x01, 0xF0, 0x9A, 0xFA, + 0x00, 0xF0, 0xE6, 0xFB, 0x00, 0x28, 0xD9, 0xD1, 0xBD, 0xE8, 0xF0, 0x87, 0x38, 0xB5, 0x0C, 0x46, + 0x05, 0x46, 0x05, 0xF0, 0x88, 0xF9, 0x69, 0x46, 0x28, 0x46, 0x05, 0xF0, 0xBE, 0xF9, 0x00, 0x99, + 0x21, 0x42, 0xF8, 0xD1, 0x38, 0xBD, 0x00, 0x00, 0xBC, 0x47, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x70, 0xB5, 0x0D, 0x46, 0xA0, 0xF1, 0x10, 0x01, 0x03, 0x29, 0x01, 0xD8, 0x5C, 0x48, 0x05, 0xE0, + 0xA0, 0xF1, 0x30, 0x01, 0x0A, 0x29, 0x06, 0xD8, 0x59, 0x48, 0x20, 0x30, 0x50, 0xF8, 0x31, 0x30, + 0x00, 0xEB, 0xC1, 0x00, 0x0D, 0xE0, 0x62, 0x28, 0x02, 0xD0, 0x4F, 0xF0, 0x00, 0x04, 0x10, 0xE0, + 0x53, 0x49, 0xA0, 0xF1, 0x62, 0x00, 0xA1, 0xF1, 0x08, 0x01, 0x51, 0xF8, 0x30, 0x30, 0x01, 0xEB, + 0xC0, 0x00, 0x4F, 0xF0, 0x01, 0x04, 0x40, 0x68, 0x90, 0x42, 0x02, 0xD1, 0x11, 0x46, 0x28, 0x46, + 0x98, 0x47, 0x20, 0x46, 0x70, 0xBD, 0x4B, 0x49, 0x01, 0x20, 0x08, 0x60, 0x04, 0x21, 0xFF, 0xF7, + 0xBD, 0xBF, 0x48, 0x49, 0x00, 0x20, 0x08, 0x60, 0x04, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xB6, 0xBF, + 0x05, 0xF0, 0xA1, 0xBE, 0x10, 0xB5, 0xF0, 0xF7, 0xC1, 0xFF, 0x43, 0x49, 0x0E, 0x20, 0x08, 0x60, + 0xF0, 0xF7, 0xBA, 0xFF, 0x02, 0x21, 0x05, 0x20, 0x01, 0xF0, 0x3C, 0xFA, 0xBD, 0xE8, 0x10, 0x40, + 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0xFF, 0xF7, 0xA1, 0xBF, 0x3C, 0x49, 0x02, 0x78, 0x0A, 0x70, + 0x42, 0x78, 0x4A, 0x70, 0x01, 0x78, 0x4B, 0x07, 0x39, 0x49, 0x0A, 0x68, 0x02, 0xD5, 0x42, 0xF0, + 0x04, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0x02, 0x78, 0x12, 0x07, 0x0A, 0x68, + 0x02, 0xD5, 0x42, 0xF0, 0x02, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x02, 0x02, 0x0A, 0x60, 0x02, 0x78, + 0xD2, 0x06, 0x0A, 0x68, 0x02, 0xD5, 0x42, 0xF0, 0x01, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x01, 0x02, + 0x0A, 0x60, 0x00, 0x78, 0x40, 0x06, 0x02, 0xD5, 0x42, 0xF0, 0x10, 0x00, 0x01, 0xE0, 0x22, 0xF0, + 0x10, 0x00, 0x08, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x70, 0xBF, 0x00, 0x78, 0x28, 0xB1, + 0x01, 0x28, 0x05, 0xD1, 0x10, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x68, 0xBF, 0x04, 0x21, 0xFA, 0xE7, + 0x70, 0x47, 0x02, 0x78, 0x1E, 0x48, 0x01, 0x68, 0x22, 0xB1, 0x01, 0x2A, 0x05, 0xD0, 0x02, 0x2A, + 0x08, 0xD1, 0x0B, 0xE0, 0x21, 0xF0, 0x08, 0x01, 0x01, 0xE0, 0x41, 0xF0, 0x08, 0x01, 0x21, 0xF0, + 0x40, 0x01, 0x01, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x50, 0xBF, 0x21, 0xF0, 0x08, 0x01, + 0x41, 0xF0, 0x40, 0x01, 0xF5, 0xE7, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, + 0x70, 0x47, 0x00, 0x21, 0x00, 0x78, 0x0A, 0x46, 0x83, 0x07, 0x01, 0xD5, 0x20, 0x21, 0x00, 0x22, + 0xC0, 0x07, 0x01, 0xD0, 0x41, 0xF0, 0x02, 0x01, 0x0A, 0x48, 0xC0, 0xE9, 0x00, 0x12, 0x0A, 0x4A, + 0x00, 0x20, 0xC2, 0xE9, 0x00, 0x00, 0x70, 0x47, 0x70, 0x47, 0x00, 0xF0, 0xBF, 0xBC, 0x00, 0x00, + 0x74, 0x6C, 0x01, 0x00, 0x44, 0x07, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0xDC, 0x48, 0x10, 0x00, + 0x48, 0x07, 0x10, 0x00, 0x48, 0x05, 0x10, 0x00, 0x50, 0x05, 0x10, 0x00, 0x0B, 0x46, 0x10, 0xB5, + 0x00, 0x21, 0xA0, 0x38, 0x09, 0x28, 0x06, 0xD8, 0xFE, 0x49, 0x51, 0xF8, 0x20, 0x40, 0x11, 0x46, + 0x18, 0x46, 0xA0, 0x47, 0x01, 0x46, 0x08, 0x46, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, 0x70, 0xB5, + 0x00, 0x23, 0x00, 0x29, 0x11, 0xDD, 0x02, 0x78, 0x49, 0x1E, 0x03, 0x2A, 0x0D, 0xD2, 0xF5, 0x4D, + 0x40, 0x1C, 0x28, 0x35, 0x55, 0xF8, 0x32, 0x40, 0x05, 0xEB, 0xC2, 0x02, 0x52, 0x68, 0x00, 0x2A, + 0x03, 0xDB, 0x91, 0x42, 0x01, 0xD1, 0xA0, 0x47, 0x03, 0x46, 0x18, 0x46, 0x70, 0xBD, 0x10, 0xB5, + 0x00, 0x78, 0x00, 0x21, 0xC0, 0x07, 0x00, 0xD0, 0x01, 0x21, 0xEB, 0x48, 0x02, 0x68, 0x8A, 0x42, + 0x04, 0xD0, 0x01, 0x60, 0x04, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xE8, 0xFE, 0x01, 0x20, 0x10, 0xBD, + 0x10, 0xB5, 0x10, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xE1, 0xFE, 0xE3, 0x49, 0x00, 0x20, 0x08, 0x60, + 0x01, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x00, 0x23, 0x00, 0x29, 0x0F, 0xDD, 0x02, 0x78, 0x49, 0x1E, + 0x05, 0x2A, 0x0B, 0xD2, 0xDB, 0x4D, 0x40, 0x1C, 0x40, 0x35, 0x55, 0xF8, 0x32, 0x40, 0x05, 0xEB, + 0xC2, 0x02, 0x52, 0x68, 0x91, 0x42, 0x01, 0xD1, 0xA0, 0x47, 0x03, 0x46, 0x18, 0x46, 0x70, 0xBD, + 0x10, 0xB5, 0x00, 0x78, 0xC2, 0x07, 0xD5, 0x48, 0x01, 0x68, 0x02, 0xD0, 0x41, 0xF0, 0x02, 0x01, + 0x01, 0xE0, 0x21, 0xF0, 0x02, 0x01, 0x01, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xB6, 0xFE, + 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0xC2, 0x07, 0xCC, 0x48, 0x01, 0x68, 0x02, 0xD0, + 0x41, 0xF0, 0x04, 0x01, 0x01, 0xE0, 0x21, 0xF0, 0x04, 0x01, 0x01, 0x60, 0x08, 0x21, 0x01, 0x20, + 0xFF, 0xF7, 0xA4, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x01, 0x78, 0xCB, 0x07, 0xC3, 0x49, + 0x0A, 0x68, 0x02, 0xD0, 0x42, 0xF0, 0x08, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x08, 0x02, 0x0A, 0x60, + 0x00, 0x78, 0x80, 0x07, 0x02, 0xD5, 0x42, 0xF0, 0x40, 0x00, 0x01, 0xE0, 0x22, 0xF0, 0x40, 0x00, + 0x08, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x89, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, + 0x00, 0x21, 0x03, 0x78, 0x0A, 0x46, 0x9C, 0x07, 0x01, 0xD5, 0x20, 0x21, 0x00, 0x22, 0x5C, 0x07, + 0x01, 0xD5, 0x41, 0xF0, 0x02, 0x01, 0x1C, 0x07, 0x01, 0xD5, 0x41, 0xF0, 0x04, 0x01, 0xDC, 0x06, + 0x01, 0xD5, 0x41, 0xF0, 0x08, 0x01, 0x9B, 0x06, 0x01, 0xD5, 0x41, 0xF0, 0x10, 0x01, 0x43, 0x78, + 0x5C, 0x07, 0x01, 0xD5, 0x41, 0xF0, 0x40, 0x01, 0x1C, 0x07, 0x01, 0xD5, 0x41, 0xF0, 0x80, 0x01, + 0xDC, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x71, 0x9C, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x00, 0x71, + 0x5C, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x61, 0x1B, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x00, 0x61, + 0x80, 0x78, 0xC3, 0x07, 0x01, 0xD0, 0x41, 0xF4, 0x80, 0x51, 0x83, 0x07, 0x01, 0xD5, 0x41, 0xF4, + 0x00, 0x51, 0x43, 0x07, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x41, 0x03, 0x07, 0x01, 0xD5, 0x41, 0xF4, + 0x00, 0x41, 0xC3, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x31, 0x83, 0x06, 0x01, 0xD5, 0x41, 0xF4, + 0x00, 0x31, 0x43, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x21, 0x00, 0x06, 0x01, 0xD5, 0x41, 0xF4, + 0x00, 0x21, 0x8F, 0x48, 0xC0, 0xE9, 0x00, 0x12, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, + 0x70, 0xB5, 0x00, 0x23, 0x00, 0x29, 0x0F, 0xDD, 0x02, 0x78, 0x49, 0x1E, 0x0B, 0x2A, 0x0B, 0xD2, + 0x84, 0x4D, 0x40, 0x1C, 0x68, 0x35, 0x55, 0xF8, 0x32, 0x40, 0x05, 0xEB, 0xC2, 0x02, 0x52, 0x68, + 0x91, 0x42, 0x01, 0xD1, 0xA0, 0x47, 0x03, 0x46, 0x18, 0x46, 0x70, 0xBD, 0x01, 0x46, 0x00, 0x20, + 0x09, 0x78, 0x05, 0x29, 0x06, 0xD2, 0x7B, 0x48, 0xC0, 0x30, 0x50, 0xF8, 0x21, 0x20, 0x00, 0x21, + 0x08, 0x46, 0x10, 0x47, 0x70, 0x47, 0x10, 0xB5, 0x05, 0xF0, 0xF5, 0xFC, 0x01, 0x20, 0x10, 0xBD, + 0x10, 0xB5, 0x00, 0xF0, 0x93, 0xFB, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x61, + 0x00, 0x20, 0xFF, 0xF7, 0xFB, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x80, 0x51, + 0x00, 0x20, 0xFF, 0xF7, 0xF3, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x01, + 0x00, 0x20, 0xFF, 0xF7, 0xEB, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0xC0, 0x07, + 0x02, 0xD0, 0x00, 0xF0, 0x02, 0xFB, 0x01, 0xE0, 0x00, 0xF0, 0xF6, 0xFA, 0x01, 0x20, 0x10, 0xBD, + 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, 0x02, 0x24, 0x81, 0x07, 0x01, 0xD5, + 0x44, 0xF0, 0x04, 0x04, 0x40, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x08, 0x04, 0x94, 0xB1, 0xF0, 0xF7, + 0xDD, 0xFD, 0x5C, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, 0xD5, 0xFD, 0x02, 0x21, + 0x05, 0x20, 0x01, 0xF0, 0x57, 0xF8, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0xFF, 0xF7, 0xBE, 0xFD, + 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, + 0x00, 0xD0, 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x41, 0x07, 0x01, 0xD5, + 0x44, 0xF0, 0x04, 0x04, 0x00, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x08, 0x04, 0x6C, 0xB1, 0xF0, 0xF7, + 0xB5, 0xFD, 0x49, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, 0xAD, 0xFD, 0x02, 0x21, + 0x00, 0x20, 0xFF, 0xF7, 0x9B, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, + 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, + 0x02, 0x04, 0x41, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x04, 0x04, 0x00, 0x07, 0x01, 0xD5, 0x44, 0xF0, + 0x08, 0x04, 0x74, 0xB1, 0xF0, 0xF7, 0x92, 0xFD, 0x38, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, + 0xF0, 0xF7, 0x8A, 0xFD, 0x4F, 0xF4, 0x00, 0x11, 0x00, 0x20, 0xFF, 0xF7, 0x77, 0xFD, 0x01, 0x20, + 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, + 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x41, 0x07, 0x01, 0xD5, 0x44, 0xF0, + 0x04, 0x04, 0x01, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x08, 0x04, 0xC1, 0x06, 0x01, 0xD5, 0x44, 0xF0, + 0x10, 0x04, 0x81, 0x06, 0x01, 0xD5, 0x44, 0xF0, 0x20, 0x04, 0x41, 0x06, 0x01, 0xD5, 0x44, 0xF0, + 0x40, 0x04, 0x01, 0x06, 0x01, 0xD5, 0x44, 0xF0, 0x80, 0x04, 0xC1, 0x05, 0x01, 0xD5, 0x44, 0xF4, + 0x80, 0x74, 0x81, 0x05, 0x01, 0xD5, 0x44, 0xF4, 0x00, 0x74, 0x40, 0x05, 0x01, 0xD5, 0x44, 0xF4, + 0x80, 0x64, 0x6C, 0xB1, 0xF0, 0xF7, 0x52, 0xFD, 0x19, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, + 0xF0, 0xF7, 0x4A, 0xFD, 0x80, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0x38, 0xFD, 0x01, 0x20, 0x10, 0xBD, + 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, 0x01, 0x24, + 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x40, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x04, 0x04, + 0x0C, 0xB3, 0xF0, 0xF7, 0x33, 0xFD, 0x0B, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, + 0x2B, 0xFD, 0x11, 0xE0, 0xEC, 0x6C, 0x01, 0x00, 0x44, 0x07, 0x10, 0x00, 0x48, 0x07, 0x10, 0x00, + 0x48, 0x05, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0x2C, 0x07, 0x10, 0x00, 0x30, 0x07, 0x10, 0x00, + 0x38, 0x07, 0x10, 0x00, 0x3C, 0x07, 0x10, 0x00, 0x4F, 0xF4, 0x80, 0x01, 0x00, 0x20, 0xFF, 0xF7, + 0x05, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0x00, 0x24, + 0xC1, 0x07, 0x00, 0xD0, 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x40, 0x07, + 0x01, 0xD5, 0x44, 0xF0, 0x04, 0x04, 0x74, 0xB1, 0xF0, 0xF7, 0x00, 0xFD, 0x2B, 0x48, 0x01, 0x68, + 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, 0xF8, 0xFC, 0x4F, 0xF4, 0x80, 0x61, 0x00, 0x20, 0xFF, 0xF7, + 0xE5, 0xFC, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0x00, 0x24, + 0x51, 0x28, 0x3D, 0xD0, 0x18, 0xDC, 0x30, 0x28, 0x36, 0xD0, 0x0C, 0xDC, 0x11, 0x28, 0x2F, 0xD0, + 0x04, 0xDC, 0x01, 0x28, 0x29, 0xD0, 0x10, 0x28, 0x30, 0xD1, 0x29, 0xE0, 0x12, 0x28, 0x27, 0xD0, + 0x13, 0x28, 0x2B, 0xD1, 0x24, 0xE0, 0x31, 0x28, 0x26, 0xD0, 0x32, 0x28, 0x24, 0xD0, 0x33, 0x28, + 0x22, 0xD0, 0x50, 0x28, 0x22, 0xD1, 0x23, 0xE0, 0x73, 0x28, 0x24, 0xD0, 0x0C, 0xDC, 0x70, 0x28, + 0x21, 0xD0, 0x04, 0xDC, 0x52, 0x28, 0x1B, 0xD0, 0x53, 0x28, 0x17, 0xD1, 0x18, 0xE0, 0x71, 0x28, + 0x19, 0xD0, 0x72, 0x28, 0x12, 0xD1, 0x16, 0xE0, 0x74, 0x28, 0x14, 0xD0, 0x75, 0x28, 0x12, 0xD0, + 0x76, 0x28, 0x10, 0xD0, 0x77, 0x28, 0x09, 0xD1, 0x0D, 0xE0, 0x00, 0xF0, 0x90, 0xFC, 0x01, 0xE0, + 0x00, 0xF0, 0x25, 0xFD, 0x01, 0x24, 0x01, 0xE0, 0x00, 0xF0, 0x41, 0xFD, 0x20, 0x46, 0x10, 0xBD, + 0x00, 0xF0, 0x2B, 0xFD, 0xF6, 0xE7, 0x00, 0xF0, 0x0B, 0xFE, 0xF3, 0xE7, 0x34, 0x07, 0x10, 0x00, + 0x1B, 0x49, 0x08, 0xB5, 0x1B, 0x4C, 0x00, 0x20, 0x08, 0x60, 0x20, 0x60, 0x00, 0xF0, 0x77, 0xFC, + 0x00, 0xF0, 0x02, 0xFF, 0x6B, 0x46, 0x00, 0x22, 0x19, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x5C, 0xFE, + 0x00, 0x98, 0xC0, 0x07, 0x05, 0xD0, 0x01, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x38, 0xFE, 0xFF, 0xF7, + 0x4F, 0xFC, 0x00, 0x98, 0x00, 0x07, 0x0B, 0xD5, 0x08, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x2F, 0xFE, + 0x20, 0x68, 0x08, 0x21, 0x40, 0xF0, 0x08, 0x00, 0x20, 0x60, 0x01, 0x20, 0xFF, 0xF7, 0x6E, 0xFC, + 0x00, 0x98, 0xC0, 0x06, 0xDE, 0xD5, 0x10, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x20, 0xFE, 0x20, 0x68, + 0x08, 0x21, 0x20, 0xF0, 0x08, 0x00, 0x20, 0x60, 0x01, 0x20, 0xFF, 0xF7, 0x5F, 0xFC, 0xD1, 0xE7, + 0x44, 0x07, 0x10, 0x00, 0x48, 0x07, 0x10, 0x00, 0x1F, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x70, + 0x81, 0x70, 0x70, 0x47, 0x10, 0xB5, 0x1C, 0x4C, 0x03, 0x46, 0xA0, 0x78, 0x10, 0x28, 0x14, 0xD2, + 0x0F, 0x29, 0x00, 0xD9, 0x0F, 0x21, 0x19, 0x48, 0x22, 0x78, 0x00, 0xEB, 0x02, 0x10, 0x0A, 0x46, + 0x00, 0xF8, 0x01, 0x1B, 0x19, 0x46, 0x06, 0xF0, 0x5D, 0xFE, 0x20, 0x78, 0x40, 0x1C, 0x00, 0xF0, + 0x0F, 0x00, 0x20, 0x70, 0xA0, 0x78, 0x40, 0x1C, 0xA0, 0x70, 0x10, 0xBD, 0x70, 0xB5, 0x0E, 0x4C, + 0x00, 0x25, 0xA1, 0x78, 0x91, 0xB1, 0x0D, 0x49, 0x62, 0x78, 0x01, 0xEB, 0x02, 0x11, 0x11, 0xF8, + 0x01, 0x5B, 0x2A, 0x46, 0x06, 0xF0, 0x46, 0xFE, 0x60, 0x78, 0x40, 0x1C, 0x00, 0xF0, 0x0F, 0x00, + 0x60, 0x70, 0x72, 0xB6, 0xA0, 0x78, 0x40, 0x1E, 0xA0, 0x70, 0x62, 0xB6, 0x28, 0x46, 0x70, 0xBD, + 0x01, 0x48, 0x80, 0x78, 0x70, 0x47, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0xDC, 0x47, 0x10, 0x00, + 0x70, 0xB5, 0x14, 0x46, 0x00, 0x20, 0x06, 0xF0, 0x51, 0xFF, 0x00, 0xF0, 0x01, 0x05, 0x01, 0x20, + 0x06, 0xF0, 0x4C, 0xFF, 0x00, 0xF0, 0x01, 0x00, 0x45, 0xEA, 0x00, 0x10, 0x20, 0x70, 0x01, 0x20, + 0x70, 0xBD, 0x80, 0x20, 0x10, 0x70, 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x14, 0x46, 0x05, 0xF0, + 0xCE, 0xFA, 0x53, 0x21, 0x21, 0x70, 0x54, 0x21, 0x61, 0x70, 0x01, 0x0A, 0xA1, 0x70, 0xE0, 0x70, + 0x05, 0xF0, 0xC9, 0xFA, 0x20, 0x71, 0x05, 0x20, 0x10, 0xBD, 0x38, 0xB5, 0x14, 0x46, 0x74, 0x4A, + 0x13, 0x68, 0x59, 0x8E, 0x98, 0x8E, 0x93, 0xF8, 0x36, 0x30, 0xDB, 0x07, 0x0A, 0xD0, 0x03, 0x0A, + 0x23, 0x70, 0x60, 0x70, 0x0D, 0x0A, 0xA5, 0x70, 0xE1, 0x70, 0x23, 0x71, 0x60, 0x71, 0xA5, 0x71, + 0xE1, 0x71, 0x09, 0xE0, 0x0B, 0x0A, 0x23, 0x70, 0x61, 0x70, 0x05, 0x0A, 0xA5, 0x70, 0xE0, 0x70, + 0x23, 0x71, 0x61, 0x71, 0xA5, 0x71, 0xE0, 0x71, 0x10, 0x68, 0x90, 0xF8, 0x31, 0x10, 0x21, 0x72, + 0x10, 0xF8, 0x30, 0x1F, 0x61, 0x72, 0x90, 0xF8, 0x31, 0x04, 0x8D, 0xF8, 0x00, 0x00, 0x01, 0x21, + 0x68, 0x46, 0x05, 0xF0, 0x1F, 0xFB, 0xA0, 0x72, 0x0B, 0x20, 0x38, 0xBD, 0x00, 0x20, 0x10, 0x70, + 0x10, 0x20, 0x50, 0x70, 0x5A, 0x48, 0x01, 0x68, 0x49, 0x8A, 0x09, 0x0A, 0x91, 0x70, 0x01, 0x68, + 0x89, 0x7C, 0xD1, 0x70, 0x00, 0x68, 0x01, 0x7E, 0x11, 0x71, 0x40, 0x7E, 0x50, 0x71, 0x06, 0x20, + 0x70, 0x47, 0x08, 0xB5, 0x02, 0x23, 0x00, 0x93, 0x52, 0x4B, 0x00, 0xF0, 0x8D, 0xF8, 0x02, 0x20, + 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x4E, 0x4B, 0x9B, 0x1C, 0x00, 0xF0, 0x84, 0xF8, + 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x4A, 0x4B, 0xDB, 0x1C, 0x00, 0xF0, + 0x7B, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x45, 0x4B, 0x1B, 0x1D, + 0x00, 0xF0, 0x72, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x41, 0x4B, + 0x5B, 0x1D, 0x00, 0xF0, 0x69, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, + 0x3C, 0x4B, 0x9B, 0x1D, 0x00, 0xF0, 0x60, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x02, 0x23, + 0x00, 0x93, 0x38, 0x4B, 0xDB, 0x1D, 0x00, 0xF0, 0x57, 0xF8, 0x02, 0x20, 0x08, 0xBD, 0x08, 0xB5, + 0x02, 0x23, 0x00, 0x93, 0x33, 0x4B, 0x09, 0x33, 0x00, 0xF0, 0x4E, 0xF8, 0x02, 0x20, 0x08, 0xBD, + 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x2F, 0x4B, 0x0B, 0x33, 0x00, 0xF0, 0x45, 0xF8, 0x01, 0x20, + 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x2A, 0x4B, 0x0C, 0x33, 0x00, 0xF0, 0x3C, 0xF8, + 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x26, 0x4B, 0x0D, 0x33, 0x00, 0xF0, + 0x33, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x46, 0x04, 0x46, 0x00, 0x78, + 0x49, 0x1E, 0xCE, 0xB2, 0x00, 0x25, 0x63, 0x1C, 0xA0, 0xF1, 0x20, 0x01, 0x04, 0x29, 0x09, 0xD8, + 0x1D, 0x49, 0x01, 0xEB, 0x80, 0x00, 0x31, 0x46, 0x50, 0xF8, 0x80, 0x4C, 0x18, 0x46, 0xA0, 0x47, + 0x05, 0x46, 0x16, 0xE0, 0xA0, 0xF1, 0x30, 0x01, 0x0B, 0x29, 0x12, 0xD8, 0x16, 0x49, 0x14, 0x31, + 0x01, 0xEB, 0x80, 0x00, 0x31, 0x46, 0x50, 0xF8, 0xC0, 0x5C, 0x18, 0x46, 0xA8, 0x47, 0x05, 0x46, + 0x3E, 0xB1, 0x39, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xCD, 0xFE, 0x01, 0x21, 0x03, 0x20, 0x04, 0xF0, + 0xAA, 0xFC, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x70, 0xB5, 0x1D, 0x46, 0x04, 0x9C, 0x16, 0x46, + 0x39, 0xB1, 0xA1, 0x42, 0x00, 0xD9, 0x21, 0x46, 0x0A, 0x46, 0x01, 0x46, 0x18, 0x46, 0x06, 0xF0, + 0x29, 0xFD, 0x22, 0x46, 0x29, 0x46, 0x30, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x06, 0xF0, 0x22, 0xBD, + 0x20, 0x07, 0x10, 0x00, 0xDC, 0x48, 0x10, 0x00, 0xC0, 0x6D, 0x01, 0x00, 0x10, 0xB5, 0x4F, 0xF4, + 0x86, 0x71, 0x4F, 0x48, 0x06, 0xF0, 0xB7, 0xFD, 0x4D, 0x49, 0x01, 0x20, 0xC1, 0xF8, 0x04, 0x01, + 0x4C, 0x48, 0x00, 0x21, 0x41, 0x60, 0x01, 0x70, 0x06, 0xF0, 0x3E, 0xFE, 0x00, 0x21, 0xBD, 0xE8, + 0x10, 0x40, 0x01, 0x20, 0x05, 0xF0, 0x5B, 0xBD, 0x10, 0xB5, 0x72, 0xB6, 0x00, 0x20, 0x45, 0x49, + 0x08, 0x70, 0x06, 0xF0, 0x31, 0xFE, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xB5, 0x72, 0xB6, 0x01, 0x20, + 0x40, 0x49, 0x08, 0x70, 0x3E, 0x48, 0xD0, 0xF8, 0x08, 0x01, 0x08, 0xB1, 0x06, 0xF0, 0xC8, 0xFD, + 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xB5, 0x72, 0xB6, 0x39, 0x49, 0x3A, 0x4B, 0x0A, 0x46, 0xD1, 0xF8, + 0x08, 0x41, 0xD2, 0xF8, 0x00, 0x21, 0x52, 0x1C, 0x20, 0x2C, 0x07, 0xD2, 0x64, 0x1C, 0x22, 0xF0, + 0x20, 0x02, 0xC1, 0xF8, 0x08, 0x41, 0xC1, 0xF8, 0x00, 0x21, 0x0F, 0xE0, 0xD1, 0xF8, 0x04, 0x41, + 0x22, 0xF0, 0x20, 0x02, 0x64, 0x1C, 0xC1, 0xF8, 0x00, 0x21, 0x24, 0xF0, 0x20, 0x02, 0xC1, 0xF8, + 0x04, 0x21, 0x5A, 0x68, 0x52, 0x1C, 0x5A, 0x60, 0xD1, 0xF8, 0x00, 0x21, 0x04, 0x68, 0x01, 0xEB, + 0xC2, 0x02, 0x14, 0x60, 0x40, 0x68, 0x50, 0x60, 0x18, 0x78, 0x01, 0x28, 0x05, 0xD1, 0xD1, 0xF8, + 0x08, 0x01, 0x01, 0x28, 0x01, 0xD1, 0x06, 0xF0, 0x93, 0xFD, 0x62, 0xB6, 0x10, 0xBD, 0x20, 0x4A, + 0xD2, 0xF8, 0x08, 0x01, 0x00, 0x28, 0x0E, 0xD0, 0xD2, 0xF8, 0x04, 0x01, 0x02, 0xEB, 0xC0, 0x00, + 0xC3, 0x79, 0x23, 0xF0, 0x3F, 0x03, 0xC3, 0x71, 0x92, 0xF8, 0x08, 0x21, 0x52, 0x1E, 0x02, 0xF0, + 0x3F, 0x02, 0x13, 0x43, 0xC3, 0x71, 0x70, 0x47, 0x10, 0xB5, 0x72, 0xB6, 0x14, 0x48, 0xD0, 0xF8, + 0x08, 0x11, 0x59, 0xB1, 0x49, 0x1E, 0xC0, 0xF8, 0x08, 0x11, 0xD0, 0xF8, 0x04, 0x21, 0x02, 0xF1, + 0x01, 0x02, 0x22, 0xF0, 0x20, 0x02, 0xC0, 0xF8, 0x04, 0x21, 0x05, 0xD1, 0x0D, 0x48, 0x00, 0x78, + 0x01, 0x28, 0x01, 0xD1, 0x06, 0xF0, 0xC0, 0xFD, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xB5, 0x72, 0xB6, + 0x00, 0x20, 0x07, 0x49, 0x01, 0x22, 0xC1, 0xF8, 0x08, 0x01, 0xC1, 0xE9, 0x40, 0x02, 0x05, 0x49, + 0x48, 0x60, 0x08, 0x78, 0x01, 0x28, 0x01, 0xD1, 0x06, 0xF0, 0xAE, 0xFD, 0x62, 0xB6, 0x10, 0xBD, + 0x40, 0x42, 0x01, 0x20, 0x04, 0x07, 0x10, 0x00, 0x18, 0x49, 0x00, 0x22, 0x0A, 0x80, 0x4A, 0x80, + 0x4F, 0xF4, 0x70, 0x42, 0x8A, 0x80, 0x16, 0x4A, 0xCA, 0x80, 0x16, 0x4A, 0x0A, 0x81, 0x16, 0x4A, + 0xC0, 0xE9, 0x00, 0x21, 0x05, 0x21, 0x01, 0x72, 0x70, 0x47, 0x1C, 0xB5, 0x12, 0x49, 0xAD, 0xF8, + 0x04, 0x00, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x04, 0x20, 0x09, 0x1F, 0x8D, 0xF8, 0x07, 0x00, + 0x00, 0x91, 0x68, 0x46, 0x05, 0xF0, 0x59, 0xFE, 0x1C, 0xBD, 0x30, 0xB4, 0x03, 0x46, 0x0A, 0x4A, + 0x00, 0x20, 0x14, 0x78, 0x9C, 0x42, 0x02, 0xD1, 0x30, 0xBC, 0x05, 0xF0, 0x84, 0xBE, 0x40, 0x1C, + 0xC0, 0xB2, 0x52, 0x1D, 0x05, 0x28, 0xF4, 0xD3, 0x30, 0xBC, 0x70, 0x47, 0xEA, 0x48, 0x10, 0x00, + 0x4C, 0x62, 0x01, 0x20, 0xD0, 0x5E, 0x01, 0x20, 0x04, 0x6E, 0x01, 0x00, 0x10, 0xB5, 0x88, 0xB3, + 0xA3, 0x49, 0xA4, 0x4A, 0x09, 0x78, 0x37, 0x29, 0x71, 0xD0, 0x11, 0xDC, 0xA1, 0xF1, 0x20, 0x01, + 0x17, 0x29, 0x2C, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x2B, 0x2B, 0x2B, + 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x00, + 0x97, 0x4B, 0x70, 0x29, 0x5B, 0x78, 0x26, 0xD0, 0x0C, 0xDC, 0x3B, 0x29, 0x57, 0xD0, 0x04, 0xDC, + 0x38, 0x29, 0x54, 0xD0, 0x3A, 0x29, 0x12, 0xD1, 0x51, 0xE0, 0x60, 0x29, 0x19, 0xD0, 0x61, 0x29, + 0x0D, 0xD1, 0x16, 0xE0, 0x73, 0x29, 0x28, 0xD0, 0x05, 0xDC, 0x71, 0x29, 0x15, 0xD0, 0x72, 0x29, + 0x05, 0xD1, 0x14, 0xE0, 0x0B, 0xE0, 0x85, 0x29, 0x0B, 0xD0, 0x86, 0x29, 0x09, 0xD0, 0xC1, 0xB2, + 0x87, 0x48, 0xFF, 0xF7, 0x8F, 0xFD, 0x01, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x6C, 0xFB, 0x00, 0x20, + 0x10, 0xBD, 0x02, 0x20, 0x10, 0xBD, 0x93, 0x70, 0xF9, 0xE7, 0xD3, 0x70, 0xF7, 0xE7, 0x90, 0x78, + 0x01, 0x28, 0x08, 0xD0, 0x00, 0x28, 0xF2, 0xD1, 0x7F, 0x48, 0x81, 0xB2, 0x5F, 0xF0, 0x72, 0x00, + 0xFF, 0xF7, 0x93, 0xFF, 0xEB, 0xE7, 0x7D, 0x48, 0xF7, 0xE7, 0xD0, 0x78, 0x01, 0x28, 0x05, 0xD0, + 0x00, 0x28, 0xE4, 0xD1, 0x7A, 0x48, 0x81, 0xB2, 0x73, 0x20, 0xF1, 0xE7, 0x79, 0x4C, 0x7A, 0x49, + 0x20, 0x68, 0x90, 0xF8, 0x31, 0x00, 0x42, 0x00, 0x71, 0x48, 0x10, 0x30, 0x06, 0xF0, 0xD2, 0xFB, + 0x20, 0x68, 0x10, 0xF8, 0x30, 0x1F, 0x4A, 0x00, 0x6D, 0x49, 0x40, 0x78, 0x10, 0x31, 0x01, 0xEB, + 0x40, 0x00, 0x72, 0x49, 0x06, 0xF0, 0xC6, 0xFB, 0x69, 0x48, 0x10, 0x30, 0xE3, 0xE7, 0xC1, 0xB2, + 0x52, 0x68, 0x67, 0x48, 0xFF, 0xF7, 0x57, 0xFE, 0x6D, 0x49, 0x08, 0x70, 0x01, 0x20, 0x10, 0xBD, + 0x2D, 0xE9, 0xF0, 0x5F, 0xDF, 0xF8, 0x88, 0xB1, 0x62, 0x4E, 0x62, 0x4D, 0x89, 0x46, 0x07, 0x46, + 0x4F, 0xF0, 0x01, 0x0A, 0xAB, 0xF1, 0x10, 0x0B, 0x08, 0x36, 0x28, 0x78, 0xA8, 0x46, 0x04, 0x46, + 0x07, 0x28, 0x76, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x04, 0x21, 0x25, 0x40, 0x5C, 0x78, 0x8A, 0x00, + 0x01, 0x2F, 0x02, 0xD0, 0x02, 0x2F, 0x0C, 0xD0, 0x6B, 0xE0, 0x48, 0x46, 0xFF, 0xF7, 0x5E, 0xFF, + 0x02, 0x28, 0x02, 0xD0, 0x01, 0x28, 0x02, 0xD0, 0x63, 0xE0, 0x03, 0x24, 0x61, 0xE0, 0x02, 0x24, + 0x5F, 0xE0, 0x68, 0x78, 0x01, 0x28, 0x04, 0xD0, 0x4D, 0x48, 0x10, 0x21, 0x10, 0x38, 0x06, 0xF0, + 0x08, 0xFC, 0x54, 0x46, 0x86, 0xF8, 0x00, 0xA0, 0x53, 0xE0, 0x02, 0x2F, 0x4F, 0xD0, 0x00, 0x24, + 0x39, 0xE0, 0x02, 0x2F, 0x1A, 0xD1, 0x4E, 0x4C, 0x45, 0x48, 0xD8, 0xF8, 0x04, 0x10, 0x22, 0x78, + 0x10, 0x38, 0x06, 0xF0, 0x77, 0xFB, 0x03, 0x20, 0x30, 0x70, 0x20, 0x78, 0xB0, 0x80, 0x98, 0xF8, + 0x00, 0x00, 0x04, 0x24, 0x88, 0xF8, 0x01, 0x00, 0x88, 0xF8, 0x00, 0x40, 0x27, 0xE0, 0x00, 0x24, + 0x88, 0xF8, 0x01, 0x00, 0x2C, 0x70, 0xB8, 0xE7, 0x02, 0x2F, 0x02, 0xD0, 0x01, 0x2F, 0xF6, 0xD0, + 0x2F, 0xE0, 0xFF, 0xF7, 0xA4, 0xFE, 0x08, 0x21, 0x28, 0xB1, 0x02, 0x22, 0x32, 0x70, 0x70, 0x80, + 0xB1, 0x80, 0x05, 0x24, 0x25, 0xE0, 0x68, 0x78, 0x06, 0x28, 0x04, 0xD0, 0x00, 0x22, 0xCB, 0xF8, + 0x00, 0x20, 0xCB, 0xF8, 0x04, 0x20, 0x03, 0x20, 0x30, 0x70, 0xB1, 0x80, 0x06, 0x24, 0x18, 0xE0, + 0x02, 0x2F, 0x08, 0xD0, 0x02, 0x24, 0xC0, 0xB2, 0x88, 0xF8, 0x01, 0x00, 0x2C, 0x70, 0x29, 0x48, + 0x08, 0x30, 0xBD, 0xE8, 0xF0, 0x9F, 0x68, 0x78, 0x04, 0x28, 0x08, 0xD0, 0x0B, 0xEB, 0x09, 0x00, + 0x49, 0x46, 0x10, 0xF8, 0x01, 0x2C, 0x22, 0x48, 0x10, 0x38, 0x06, 0xF0, 0xAA, 0xFB, 0x86, 0xF8, + 0x00, 0xA0, 0xA8, 0x46, 0x28, 0x78, 0xE7, 0xE7, 0x02, 0x2F, 0x05, 0xD0, 0xB9, 0xF1, 0x08, 0x0F, + 0x93, 0xD1, 0xFF, 0xF7, 0x81, 0xFE, 0x90, 0xE7, 0xFF, 0xF7, 0x7E, 0xFE, 0x98, 0xF8, 0x00, 0x00, + 0x03, 0x24, 0x88, 0xF8, 0x01, 0x00, 0x88, 0xF8, 0x00, 0x40, 0x6E, 0xE7, 0x02, 0x2F, 0x4F, 0xF0, + 0x03, 0x04, 0xAD, 0xD0, 0xCF, 0xE7, 0x13, 0x49, 0x00, 0x22, 0x0A, 0x70, 0x4A, 0x70, 0x18, 0x4A, + 0x52, 0x1C, 0x4A, 0x60, 0x17, 0x49, 0x01, 0x60, 0x0D, 0x49, 0x10, 0x39, 0x81, 0x80, 0x10, 0x31, + 0xC1, 0x80, 0x10, 0x21, 0x01, 0x81, 0x0E, 0x21, 0x13, 0x48, 0x06, 0xF0, 0x82, 0xBB, 0x10, 0xB5, + 0x04, 0x46, 0x06, 0xF0, 0x31, 0xFC, 0x06, 0x48, 0x21, 0x68, 0x10, 0x38, 0x01, 0x60, 0x61, 0x68, + 0x41, 0x60, 0x0E, 0x48, 0xFF, 0xF7, 0x91, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x06, 0xF0, 0xC8, 0xBB, + 0x5C, 0x43, 0x01, 0x20, 0x0C, 0x07, 0x10, 0x00, 0x4C, 0x62, 0x01, 0x20, 0xC8, 0x35, 0x01, 0x20, + 0xD0, 0x5E, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, + 0xF4, 0x48, 0x10, 0x00, 0x51, 0x00, 0x01, 0x00, 0xDC, 0x48, 0x10, 0x00, 0x4C, 0x43, 0x00, 0x00, + 0x70, 0xB5, 0x0F, 0x4D, 0x48, 0x21, 0x28, 0x46, 0x2C, 0x88, 0x06, 0xF0, 0x52, 0xFB, 0x64, 0x1C, + 0x2C, 0x80, 0x70, 0xBD, 0x0A, 0x48, 0x00, 0x1F, 0x00, 0x21, 0x01, 0x60, 0x70, 0x47, 0x08, 0x49, + 0x09, 0x1F, 0x0A, 0x88, 0x02, 0x42, 0x04, 0xD0, 0xC8, 0x78, 0x18, 0xB1, 0xC8, 0x78, 0x40, 0x1E, + 0xC8, 0x70, 0x70, 0x47, 0xA5, 0x20, 0x88, 0x70, 0x88, 0x78, 0xA5, 0x28, 0xFC, 0xD0, 0x70, 0x47, + 0xE6, 0x43, 0x01, 0x20, 0x37, 0x48, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x70, 0x47, 0xC0, 0xB2, + 0x01, 0x22, 0x00, 0xF0, 0x29, 0xFB, 0xFE, 0xE7, 0x34, 0x4C, 0x00, 0x25, 0x32, 0x4F, 0xC4, 0xE9, + 0x02, 0x25, 0xC4, 0xE9, 0x00, 0x71, 0x06, 0x46, 0x00, 0x68, 0x20, 0x61, 0x70, 0x68, 0x60, 0x61, + 0xB0, 0x68, 0xA0, 0x61, 0xF0, 0x68, 0xE0, 0x61, 0x30, 0x69, 0x20, 0x62, 0x70, 0x69, 0x60, 0x62, + 0xB0, 0x69, 0xA0, 0x62, 0xF0, 0x69, 0xE0, 0x62, 0x29, 0x48, 0x90, 0x46, 0x89, 0x46, 0x00, 0x68, + 0x20, 0x63, 0x27, 0x48, 0x10, 0x38, 0x00, 0x68, 0x60, 0x63, 0x25, 0x48, 0x0C, 0x38, 0x00, 0x68, + 0xA0, 0x63, 0x23, 0x48, 0x08, 0x38, 0x00, 0x68, 0xE0, 0x63, 0x21, 0x48, 0x00, 0x1D, 0x00, 0x68, + 0x20, 0x64, 0x1F, 0x48, 0x34, 0x38, 0x00, 0x68, 0x60, 0x64, 0x1D, 0x48, 0x14, 0x38, 0x00, 0x68, + 0xC4, 0xE9, 0x12, 0x05, 0x04, 0xF0, 0x37, 0xFB, 0x20, 0x65, 0xC4, 0xE9, 0x15, 0x65, 0xE5, 0x65, + 0x25, 0x66, 0x65, 0x66, 0xA5, 0x66, 0xE5, 0x66, 0x25, 0x67, 0x65, 0x67, 0xC4, 0xE9, 0x1E, 0x57, + 0x41, 0x46, 0x48, 0x46, 0xFF, 0xF7, 0xB3, 0xFF, 0x10, 0xB5, 0x04, 0x46, 0xC0, 0xB2, 0x00, 0x22, + 0x00, 0xF0, 0xDA, 0xFA, 0x0F, 0x49, 0x08, 0x68, 0x08, 0x28, 0x03, 0xDA, 0x09, 0x4A, 0x14, 0x54, + 0x40, 0x1C, 0x08, 0x60, 0x10, 0xBD, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x08, 0xD1, 0x00, 0x22, + 0x11, 0x46, 0x13, 0x20, 0x00, 0xF0, 0xC8, 0xBA, 0x00, 0x22, 0x11, 0x46, 0x12, 0x20, 0xF9, 0xE7, + 0x70, 0x47, 0x00, 0x00, 0x70, 0xEF, 0x01, 0x20, 0xAF, 0x05, 0x50, 0xFA, 0x80, 0xEF, 0x01, 0x20, + 0x38, 0xED, 0x00, 0xE0, 0x1C, 0x07, 0x10, 0x00, 0xF4, 0x48, 0xF5, 0x4A, 0x01, 0x68, 0x91, 0x42, + 0x04, 0xD1, 0xF4, 0x49, 0x02, 0x79, 0x4A, 0x70, 0x00, 0x21, 0x01, 0x60, 0x70, 0x47, 0xF0, 0xB5, + 0x85, 0xB0, 0x40, 0xF2, 0x14, 0x71, 0xED, 0x48, 0x06, 0xF0, 0xCD, 0xFA, 0x68, 0x46, 0x05, 0xF0, + 0x11, 0xFA, 0xEA, 0x4C, 0x01, 0x26, 0x00, 0x25, 0x66, 0x70, 0xA5, 0x80, 0xA5, 0x71, 0x02, 0x20, + 0xE0, 0x71, 0x04, 0xF0, 0xD8, 0xFE, 0x20, 0x81, 0x04, 0xF0, 0xD1, 0xFE, 0x07, 0x02, 0x04, 0xF0, + 0xCE, 0xFE, 0x47, 0xEA, 0x10, 0x20, 0x60, 0x81, 0x10, 0x20, 0x20, 0x82, 0x40, 0xF2, 0x32, 0x20, + 0x60, 0x82, 0xE1, 0x48, 0x00, 0x68, 0x41, 0x8A, 0xA1, 0x82, 0x01, 0x8A, 0xE1, 0x82, 0xC1, 0x8A, + 0x21, 0x83, 0x81, 0x8A, 0x61, 0x83, 0xDD, 0x49, 0xB1, 0xF8, 0xFA, 0x2E, 0xA4, 0xF8, 0x44, 0x20, + 0xB1, 0xF8, 0xF8, 0x1E, 0xA4, 0xF8, 0x46, 0x10, 0x90, 0xF8, 0x3F, 0x10, 0x21, 0x77, 0xD8, 0x49, + 0x09, 0x68, 0x09, 0x7E, 0x61, 0x77, 0x90, 0xF8, 0xA0, 0x10, 0x01, 0xF0, 0x01, 0x01, 0xA1, 0x77, + 0x01, 0x99, 0x21, 0x62, 0x00, 0x99, 0x61, 0x62, 0x02, 0x99, 0xA1, 0x62, 0xDD, 0xE9, 0x03, 0x12, + 0x41, 0xEA, 0x02, 0x21, 0xE1, 0x62, 0x81, 0x69, 0x21, 0x63, 0xC1, 0x69, 0xC4, 0xE9, 0x0D, 0x15, + 0xE5, 0x63, 0xA4, 0xF8, 0x40, 0x50, 0x84, 0xF8, 0x42, 0x50, 0x84, 0xF8, 0x43, 0x60, 0x41, 0x8E, + 0xA4, 0xF8, 0x50, 0x10, 0x81, 0x8E, 0xA4, 0xF8, 0x52, 0x10, 0x90, 0xF8, 0x31, 0x10, 0x84, 0xF8, + 0x54, 0x10, 0x90, 0xF8, 0x30, 0x00, 0x84, 0xF8, 0x55, 0x00, 0xC2, 0x48, 0xA4, 0xF8, 0x80, 0x00, + 0xC1, 0x48, 0xA4, 0xF8, 0x88, 0x00, 0xC1, 0x48, 0xA4, 0xF8, 0x8A, 0x00, 0xC0, 0x48, 0xA4, 0xF8, + 0x8C, 0x00, 0xC0, 0x48, 0xA4, 0xF8, 0x8E, 0x00, 0xBF, 0x48, 0xA4, 0xF8, 0x90, 0x00, 0xBF, 0x48, + 0xA4, 0xF8, 0x92, 0x00, 0xBE, 0x48, 0xA4, 0xF8, 0x94, 0x00, 0xBE, 0x48, 0xA4, 0xF8, 0x96, 0x00, + 0xBD, 0x48, 0xA4, 0xF8, 0x98, 0x00, 0xBD, 0x48, 0xA4, 0xF8, 0x9A, 0x00, 0xBC, 0x48, 0xA4, 0xF8, + 0x9C, 0x00, 0xAC, 0x49, 0xBB, 0x48, 0xA4, 0xF8, 0x9E, 0x00, 0x88, 0x88, 0x40, 0x1C, 0x88, 0x80, + 0xA5, 0x22, 0x22, 0x70, 0x66, 0x70, 0x60, 0x80, 0x0E, 0x70, 0x05, 0xB0, 0xF0, 0xBD, 0x70, 0xB5, + 0xA4, 0x4C, 0x05, 0x46, 0x00, 0x23, 0xA0, 0x88, 0xA0, 0x49, 0x40, 0x1C, 0x82, 0xB2, 0xA2, 0x80, + 0x28, 0x46, 0x01, 0xF0, 0x2A, 0xFB, 0x25, 0x70, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x46, 0x40, 0xF2, + 0x14, 0x71, 0x9A, 0x48, 0x06, 0xF0, 0x27, 0xFA, 0x9A, 0x4C, 0x98, 0x49, 0xA0, 0x88, 0x40, 0x1C, + 0x82, 0xB2, 0xA2, 0x80, 0x28, 0x46, 0x01, 0xF0, 0x45, 0xFB, 0x25, 0x70, 0x70, 0xBD, 0x70, 0xB5, + 0x94, 0x4C, 0x05, 0x46, 0x20, 0x78, 0xA8, 0x42, 0x04, 0xD0, 0x40, 0xF2, 0x14, 0x71, 0x8F, 0x48, + 0x06, 0xF0, 0x11, 0xFA, 0xA0, 0x48, 0xA5, 0x70, 0x0F, 0x21, 0x01, 0x60, 0x8B, 0x48, 0x8B, 0x4A, + 0x10, 0x30, 0xA0, 0x60, 0x48, 0x20, 0x10, 0x71, 0x8B, 0x48, 0x02, 0xF1, 0x58, 0x05, 0xE5, 0x60, + 0x00, 0x68, 0x90, 0xF8, 0x31, 0x10, 0x90, 0xF8, 0x30, 0x30, 0x51, 0x71, 0x01, 0xFB, 0x03, 0xF0, + 0x05, 0xEB, 0x40, 0x06, 0x93, 0x71, 0x26, 0x61, 0x08, 0x44, 0xD1, 0x71, 0x05, 0xEB, 0x40, 0x00, + 0x60, 0x61, 0x13, 0x72, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x7D, 0x4C, 0x17, 0x46, + 0x88, 0x46, 0xC0, 0x07, 0x04, 0xD0, 0x48, 0x22, 0x7E, 0x49, 0xA0, 0x68, 0x06, 0xF0, 0x42, 0xF9, + 0x79, 0x4E, 0xA8, 0x07, 0x12, 0xD5, 0x31, 0x68, 0x91, 0xF8, 0x31, 0x00, 0x91, 0xF8, 0x30, 0x10, + 0x48, 0x43, 0xA1, 0x78, 0x30, 0x29, 0x2D, 0xD0, 0x31, 0x29, 0x2D, 0xD0, 0x32, 0x29, 0x31, 0xD0, + 0x77, 0x49, 0xE3, 0x68, 0x42, 0x00, 0x18, 0x46, 0x06, 0xF0, 0x2C, 0xF9, 0x68, 0x07, 0x0E, 0xD5, + 0x30, 0x68, 0x90, 0xF8, 0x31, 0x20, 0xA0, 0x78, 0x30, 0x28, 0x25, 0xD0, 0x31, 0x28, 0x25, 0xD0, + 0x32, 0x28, 0x28, 0xD0, 0x72, 0x49, 0x52, 0x00, 0x20, 0x69, 0x06, 0xF0, 0x1B, 0xF9, 0x28, 0x07, + 0x2C, 0xD5, 0x30, 0x68, 0x90, 0xF8, 0x30, 0x20, 0xA0, 0x78, 0x30, 0x28, 0x1D, 0xD0, 0x31, 0x28, + 0x1D, 0xD0, 0x32, 0x28, 0x20, 0xD0, 0x6E, 0x49, 0x60, 0x69, 0xBD, 0xE8, 0xF0, 0x41, 0x52, 0x00, + 0x06, 0xF0, 0x08, 0xB9, 0x60, 0x49, 0xD4, 0xE7, 0x60, 0x49, 0xB8, 0xF1, 0x00, 0x0F, 0xD0, 0xD0, + 0x6A, 0x49, 0xCE, 0xE7, 0x5F, 0x49, 0xCC, 0xE7, 0x5F, 0x49, 0xDC, 0xE7, 0x5F, 0x49, 0x00, 0x2F, + 0xD9, 0xD0, 0x67, 0x49, 0xD7, 0xE7, 0x5F, 0x49, 0xD5, 0xE7, 0x5F, 0x49, 0xE4, 0xE7, 0x5F, 0x49, + 0x00, 0x2F, 0xE1, 0xD0, 0x63, 0x49, 0xDF, 0xE7, 0x5E, 0x49, 0xDD, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, + 0x4A, 0x4A, 0xA5, 0x20, 0x10, 0x70, 0x4B, 0x48, 0x81, 0x78, 0x51, 0x70, 0x01, 0x70, 0x81, 0x88, + 0x49, 0x1C, 0x81, 0x80, 0x51, 0x80, 0x70, 0x47, 0x30, 0xB5, 0x85, 0xB0, 0x0C, 0x46, 0x00, 0x21, + 0x8D, 0xF8, 0x0C, 0x10, 0x4F, 0xF4, 0x83, 0x25, 0x04, 0xAB, 0x03, 0xAA, 0x69, 0x46, 0x00, 0xF0, + 0xD0, 0xF8, 0x9D, 0xF8, 0x10, 0x00, 0x10, 0xB1, 0x11, 0x28, 0x15, 0xD0, 0x19, 0xE0, 0x9D, 0xF8, + 0x0C, 0x00, 0xB0, 0xB1, 0x00, 0x98, 0x05, 0xEB, 0x80, 0x01, 0x04, 0xF1, 0x10, 0x00, 0x0A, 0x78, + 0x93, 0x07, 0x03, 0xD0, 0x02, 0xF0, 0xFC, 0x02, 0x08, 0x32, 0x00, 0xE0, 0x12, 0x1D, 0xD2, 0xB2, + 0x06, 0xF0, 0xB8, 0xF8, 0x05, 0xB0, 0x30, 0xBD, 0x32, 0x20, 0x00, 0x22, 0x20, 0x71, 0x11, 0x46, + 0x03, 0xE0, 0x30, 0x20, 0x00, 0x22, 0x20, 0x71, 0x11, 0x46, 0x00, 0xF0, 0x25, 0xF9, 0xF1, 0xE7, + 0x70, 0xB5, 0x05, 0x46, 0x4F, 0xF4, 0xC8, 0x71, 0x28, 0x48, 0x06, 0xF0, 0x44, 0xF9, 0x29, 0x4C, + 0x26, 0x49, 0xA0, 0x88, 0x40, 0x1C, 0xA0, 0x80, 0x28, 0x46, 0xFF, 0xF7, 0xBD, 0xFF, 0x23, 0x48, + 0x25, 0x70, 0xA5, 0x21, 0x01, 0x70, 0x45, 0x70, 0xA1, 0x88, 0x41, 0x80, 0x70, 0xBD, 0x2D, 0xE9, + 0xF8, 0x4F, 0x0C, 0x46, 0x88, 0x46, 0x0E, 0x1D, 0x00, 0x23, 0x9B, 0x22, 0x04, 0x21, 0x20, 0x46, + 0x00, 0xF0, 0x60, 0xFE, 0x80, 0xBB, 0x21, 0x78, 0x00, 0x23, 0x9B, 0x22, 0x30, 0x46, 0x00, 0xF0, + 0x59, 0xFE, 0x61, 0x78, 0x88, 0x42, 0x76, 0xD1, 0x20, 0x78, 0x81, 0x07, 0x0A, 0xD0, 0x02, 0x22, + 0x02, 0xEB, 0x90, 0x05, 0x00, 0x21, 0x01, 0xE0, 0x31, 0x54, 0x40, 0x1C, 0xB0, 0xEB, 0x85, 0x0F, + 0xFA, 0xD3, 0x02, 0xE0, 0x01, 0x21, 0x01, 0xEB, 0x90, 0x05, 0x00, 0x24, 0xDF, 0xF8, 0x2C, 0xB0, + 0x4F, 0xF4, 0x83, 0x26, 0xA1, 0x46, 0x4F, 0xF0, 0x33, 0x0A, 0x00, 0xBF, 0x56, 0xF8, 0x24, 0x00, + 0x06, 0xEB, 0x84, 0x07, 0x40, 0x1C, 0x37, 0xD0, 0x00, 0x23, 0x9B, 0x22, 0x04, 0x21, 0x38, 0x46, + 0x00, 0xF0, 0x30, 0xFE, 0x08, 0xB1, 0x45, 0xE0, 0x4D, 0xE0, 0x2F, 0xE0, 0x00, 0x00, 0x01, 0x20, + 0x4B, 0x43, 0x55, 0x46, 0x58, 0x07, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xFC, 0x4C, 0x01, 0x20, + 0x24, 0x07, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x4C, 0x62, 0x01, 0x20, 0x8C, 0x2F, 0x01, 0x20, + 0xC8, 0x35, 0x01, 0x20, 0x2E, 0x44, 0x01, 0x20, 0x68, 0x5F, 0x01, 0x20, 0xC0, 0x0A, 0x01, 0x20, + 0x36, 0x0B, 0x01, 0x20, 0x6A, 0x4A, 0x01, 0x20, 0x92, 0x5F, 0x01, 0x20, 0xEA, 0x0A, 0x01, 0x20, + 0x60, 0x0B, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, 0x40, 0x07, 0x10, 0x00, 0x3C, 0x0C, 0x01, 0x20, + 0x84, 0x09, 0x01, 0x20, 0xAE, 0x09, 0x01, 0x20, 0x00, 0x94, 0x0C, 0xE0, 0x38, 0x78, 0x81, 0x07, + 0x04, 0xEB, 0x90, 0x04, 0x01, 0xD0, 0xA4, 0x1C, 0x00, 0xE0, 0x64, 0x1C, 0x60, 0x2C, 0xB5, 0xD3, + 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xD0, 0x29, 0x46, 0x40, 0x46, 0x00, 0x9A, 0x04, 0xF0, 0xEB, 0xFD, + 0x00, 0x28, 0x0C, 0xD0, 0x00, 0x22, 0x8B, 0xF8, 0x04, 0xA0, 0x11, 0x46, 0x33, 0x20, 0xBD, 0xE8, + 0xF8, 0x4F, 0x00, 0xF0, 0x81, 0xB8, 0x00, 0x22, 0x11, 0x46, 0x31, 0x20, 0xF7, 0xE7, 0xBD, 0xE8, + 0xF8, 0x8F, 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x26, 0x0E, 0x60, 0x1D, 0x46, 0x88, 0x46, 0x4F, 0xF4, + 0x83, 0x27, 0xB1, 0x46, 0x34, 0x46, 0xB3, 0x46, 0x83, 0xF8, 0x00, 0x60, 0x57, 0xF8, 0x24, 0x00, + 0x07, 0xEB, 0x84, 0x0A, 0x40, 0x1C, 0x23, 0xD0, 0x00, 0x23, 0x9B, 0x22, 0x04, 0x21, 0x50, 0x46, + 0x00, 0xF0, 0xC0, 0xFD, 0x18, 0xB1, 0x12, 0x20, 0x28, 0x70, 0x01, 0x26, 0x1C, 0xE0, 0x9A, 0xF8, + 0x02, 0x20, 0x00, 0x99, 0x9A, 0xF8, 0x00, 0x00, 0x8A, 0x42, 0x08, 0xD1, 0x02, 0x99, 0x02, 0x9A, + 0x4F, 0xF0, 0x01, 0x09, 0x09, 0x78, 0x49, 0x1C, 0x11, 0x70, 0xC8, 0xF8, 0x00, 0x40, 0x81, 0x07, + 0x04, 0xEB, 0x90, 0x04, 0x01, 0xD0, 0xA4, 0x1C, 0x00, 0xE0, 0x64, 0x1C, 0x60, 0x2C, 0xD5, 0xD3, + 0x16, 0xB9, 0xB9, 0xF1, 0x01, 0x0F, 0x0B, 0xD0, 0x56, 0xEA, 0x09, 0x06, 0x06, 0xD1, 0x11, 0x20, + 0x28, 0x70, 0x02, 0x99, 0x81, 0xF8, 0x00, 0xB0, 0xC8, 0xF8, 0x00, 0xB0, 0xBD, 0xE8, 0xFF, 0x9F, + 0xD8, 0xF8, 0x00, 0x00, 0x00, 0x23, 0x07, 0xEB, 0x80, 0x04, 0x20, 0x1D, 0x21, 0x78, 0x9B, 0x22, + 0x00, 0xF0, 0x88, 0xFD, 0x61, 0x78, 0x88, 0x42, 0x02, 0xD1, 0x85, 0xF8, 0x00, 0xB0, 0xED, 0xE7, + 0x12, 0x20, 0x28, 0x70, 0xEA, 0xE7, 0x00, 0x00, 0x19, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xA0, 0x00, + 0xC0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0x2E, 0xB8, 0x00, 0xF0, 0xDE, 0xB8, 0x38, 0xB5, 0x04, 0x46, + 0x69, 0x46, 0x18, 0x30, 0x00, 0xF0, 0xF9, 0xFD, 0x11, 0x48, 0x00, 0x99, 0x00, 0x68, 0x90, 0xF8, + 0xA0, 0x00, 0xC0, 0x07, 0x20, 0x46, 0x02, 0xD0, 0x00, 0xF0, 0x39, 0xF8, 0x38, 0xBD, 0x00, 0xF0, + 0xD5, 0xF8, 0x38, 0xBD, 0x00, 0xF0, 0x25, 0xB9, 0x09, 0x4B, 0x1B, 0x68, 0x93, 0xF8, 0xA0, 0x30, + 0xDB, 0x07, 0x01, 0xD1, 0x00, 0xF0, 0x3B, 0xB9, 0x70, 0x47, 0x05, 0x49, 0x09, 0x68, 0x91, 0xF8, + 0xA0, 0x10, 0xC9, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0x99, 0xB8, 0x00, 0xF0, 0x42, 0xB9, 0x00, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x1C, 0xB5, 0x56, 0x49, 0xD1, 0xE9, 0x00, 0x01, 0xCD, 0xE9, 0x00, 0x01, + 0x68, 0x46, 0xFF, 0xF7, 0x77, 0xFA, 0x1C, 0xBD, 0x88, 0x42, 0x0E, 0xD9, 0x90, 0x42, 0x01, 0xD3, + 0xFF, 0x20, 0x70, 0x47, 0x91, 0x42, 0x08, 0xD0, 0x40, 0x1A, 0xC0, 0xEB, 0x00, 0x20, 0x51, 0x1A, + 0xB0, 0xFB, 0xF1, 0xF0, 0x10, 0xF0, 0xFF, 0x00, 0xF3, 0xD1, 0x01, 0x20, 0x70, 0x47, 0x7C, 0xB5, + 0x05, 0x46, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x95, 0xF8, 0x4B, 0x21, 0x9D, 0xF8, 0x00, 0x00, + 0x62, 0xF3, 0x85, 0x00, 0x8D, 0xF8, 0x00, 0x00, 0x95, 0xF8, 0x3E, 0x21, 0x03, 0x2A, 0x3E, 0xD0, + 0x08, 0x2A, 0x40, 0xD0, 0x20, 0xF0, 0xC0, 0x00, 0x10, 0xF1, 0x80, 0x00, 0x8D, 0xF8, 0x00, 0x00, + 0x0A, 0x14, 0x10, 0x09, 0x8D, 0xF8, 0x01, 0x00, 0x9D, 0xF8, 0x03, 0x00, 0x39, 0x4E, 0x62, 0xF3, + 0x07, 0x10, 0x0A, 0x09, 0x8D, 0xF8, 0x02, 0x20, 0x61, 0xF3, 0x03, 0x00, 0x8D, 0xF8, 0x03, 0x00, + 0x30, 0x68, 0xB0, 0xF8, 0xA3, 0x20, 0xB0, 0xF8, 0xA1, 0x10, 0x35, 0xF8, 0x4A, 0x0F, 0xFF, 0xF7, + 0xBB, 0xFF, 0x8D, 0xF8, 0x04, 0x00, 0x30, 0x68, 0xB0, 0xF8, 0xA7, 0x20, 0xB0, 0xF8, 0xA5, 0x10, + 0x68, 0x88, 0xFF, 0xF7, 0xB1, 0xFF, 0x8D, 0xF8, 0x05, 0x00, 0x29, 0x7A, 0x9D, 0xF8, 0x06, 0x00, + 0x61, 0xF3, 0x05, 0x00, 0x8D, 0xF8, 0x06, 0x00, 0x95, 0xF8, 0xF6, 0x10, 0x09, 0x29, 0x1E, 0xD2, + 0xDF, 0xE8, 0x01, 0xF0, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x20, 0xF0, + 0xC0, 0x00, 0x40, 0x30, 0xC2, 0xE7, 0x40, 0xF0, 0xC0, 0x00, 0xBF, 0xE7, 0x00, 0x24, 0x0E, 0xE0, + 0x01, 0x24, 0x0C, 0xE0, 0x02, 0x24, 0x0A, 0xE0, 0x03, 0x24, 0x08, 0xE0, 0x04, 0x24, 0x06, 0xE0, + 0x05, 0x24, 0x04, 0xE0, 0x06, 0x24, 0x02, 0xE0, 0x07, 0x24, 0x00, 0xE0, 0x08, 0x24, 0xA1, 0x08, + 0x61, 0xF3, 0x87, 0x10, 0x8D, 0xF8, 0x06, 0x00, 0x9D, 0xF8, 0x07, 0x00, 0x64, 0xF3, 0x87, 0x10, + 0x8D, 0xF8, 0x07, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0xED, 0xF9, 0x7C, 0xBD, 0x1C, 0xB5, 0x0C, 0x4A, + 0xD2, 0xE9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0x9D, 0xF8, 0x00, 0x10, 0x21, 0xF0, 0x3C, 0x01, + 0x8D, 0xF8, 0x00, 0x10, 0x80, 0x78, 0x01, 0x28, 0x03, 0xD0, 0x05, 0x28, 0x07, 0xD1, 0x01, 0x20, + 0x00, 0xE0, 0x00, 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0xD3, 0xF9, 0x1C, 0xBD, + 0x20, 0x6E, 0x01, 0x00, 0x20, 0x07, 0x10, 0x00, 0x1C, 0xB5, 0x51, 0x49, 0xD1, 0xE9, 0x00, 0x01, + 0xCD, 0xE9, 0x00, 0x01, 0x68, 0x46, 0xFF, 0xF7, 0xC5, 0xF9, 0x1C, 0xBD, 0x1C, 0xB5, 0x4C, 0x4B, + 0xD3, 0xE9, 0x02, 0x23, 0xCD, 0xE9, 0x00, 0x23, 0x90, 0xF8, 0x3E, 0x21, 0x03, 0x2A, 0x19, 0xD0, + 0x08, 0x2A, 0x9D, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0xF0, 0x02, 0x19, 0xD0, 0x12, 0xF1, 0x20, 0x02, + 0x8D, 0xF8, 0x00, 0x20, 0x90, 0xF8, 0x3F, 0x21, 0x02, 0xF0, 0x0F, 0x02, 0x01, 0x2A, 0x11, 0xD0, + 0x02, 0x2A, 0x15, 0xD0, 0x04, 0x2A, 0x9D, 0xF8, 0x01, 0x20, 0x22, 0xF0, 0x0F, 0x02, 0x2E, 0xD0, + 0x52, 0x1C, 0x12, 0xE0, 0x9D, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0xF0, 0x02, 0x10, 0x32, 0xE7, 0xE7, + 0x30, 0x32, 0xE5, 0xE7, 0x9D, 0xF8, 0x01, 0x20, 0x22, 0xF0, 0x0F, 0x02, 0x92, 0x1C, 0x04, 0xE0, + 0x9D, 0xF8, 0x01, 0x20, 0x22, 0xF0, 0x0F, 0x02, 0xD2, 0x1C, 0x8D, 0xF8, 0x01, 0x20, 0x90, 0xF8, + 0x4B, 0x01, 0xD2, 0xB2, 0x60, 0xF3, 0x07, 0x12, 0x8D, 0xF8, 0x01, 0x20, 0xBD, 0xF8, 0x02, 0x00, + 0x0A, 0x0C, 0x62, 0xF3, 0x0B, 0x00, 0xAD, 0xF8, 0x02, 0x00, 0xBD, 0xF8, 0x03, 0x00, 0x61, 0xF3, + 0x0F, 0x10, 0xAD, 0xF8, 0x03, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x74, 0xF9, 0x1C, 0xBD, 0x12, 0x1D, + 0xE3, 0xE7, 0x1C, 0xB5, 0x23, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0xA0, 0x20, 0x93, 0x07, 0x15, 0xD5, + 0x08, 0x28, 0x13, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x12, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x12, 0x06, 0x0B, 0xD5, 0x1A, 0x4B, 0xD3, 0xE9, 0x06, 0x23, 0xCD, 0xE9, 0x00, 0x23, 0x8D, 0xF8, + 0x01, 0x00, 0xCD, 0xF8, 0x02, 0x10, 0x68, 0x46, 0xFF, 0xF7, 0x54, 0xF9, 0x1C, 0xBD, 0x1C, 0xB5, + 0x13, 0x4C, 0xD4, 0xE9, 0x08, 0x34, 0xCD, 0xE9, 0x00, 0x34, 0x8D, 0xF8, 0x01, 0x00, 0xCD, 0xF8, + 0x02, 0x10, 0x68, 0x46, 0x12, 0xB1, 0xFF, 0xF7, 0x32, 0xFB, 0x1C, 0xBD, 0xFF, 0xF7, 0x42, 0xF9, + 0x1C, 0xBD, 0x1C, 0xB5, 0x41, 0x78, 0x00, 0x29, 0x10, 0xD0, 0x05, 0x29, 0x0E, 0xD2, 0x08, 0x4A, + 0xD2, 0xE9, 0x0C, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xD0, 0xF8, 0x02, 0x10, 0xCD, 0xF8, 0x02, 0x10, + 0xC0, 0x88, 0xAD, 0xF8, 0x06, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x2C, 0xF9, 0x1C, 0xBD, 0x00, 0x00, + 0x40, 0x6E, 0x01, 0x00, 0x20, 0x07, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x41, 0x03, 0xF0, 0xCE, 0xFC, + 0x23, 0x4D, 0x00, 0x24, 0xC4, 0xEB, 0xC4, 0x01, 0x05, 0xEB, 0x81, 0x00, 0x00, 0xF1, 0x0C, 0x03, + 0x02, 0x7E, 0xC8, 0xCB, 0xCD, 0xE9, 0x02, 0x72, 0xCD, 0xE9, 0x00, 0x36, 0xD0, 0xE9, 0x01, 0x23, + 0x55, 0xF8, 0x21, 0x00, 0x00, 0x21, 0x03, 0xF0, 0x63, 0xFE, 0x18, 0xB1, 0x21, 0x46, 0x43, 0x20, + 0xFF, 0xF7, 0x45, 0xFB, 0x64, 0x1C, 0x05, 0x2C, 0xE4, 0xDB, 0x15, 0x4D, 0x00, 0x24, 0x8C, 0x35, + 0x05, 0xEB, 0xC4, 0x00, 0x00, 0x21, 0x42, 0x68, 0x55, 0xF8, 0x34, 0x00, 0x03, 0xF0, 0xD7, 0xFD, + 0x18, 0xB1, 0x21, 0x46, 0x44, 0x20, 0xFF, 0xF7, 0x32, 0xFB, 0x64, 0x1C, 0x06, 0x2C, 0xEF, 0xDB, + 0x0B, 0x4D, 0x00, 0x24, 0x15, 0xF1, 0xBC, 0x05, 0x00, 0x21, 0x55, 0xF8, 0x24, 0x00, 0x03, 0xF0, + 0x2C, 0xFD, 0x18, 0xB1, 0x21, 0x46, 0x45, 0x20, 0xFF, 0xF7, 0x21, 0xFB, 0x64, 0x1C, 0x04, 0x2C, + 0xF2, 0xDB, 0xBD, 0xE8, 0xFF, 0x81, 0x01, 0x46, 0x46, 0x20, 0xFF, 0xF7, 0x18, 0xBB, 0x00, 0x00, + 0x78, 0x6E, 0x01, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x64, 0x27, 0x07, 0x26, 0x00, 0x25, 0xFB, 0x4C, + 0xFB, 0x48, 0x04, 0xF0, 0x4A, 0xFD, 0xFA, 0x48, 0x03, 0x68, 0xD9, 0x1C, 0x40, 0xD0, 0x42, 0x68, + 0xD1, 0x1C, 0x3D, 0xD0, 0x81, 0x68, 0x11, 0xF1, 0x03, 0x0F, 0x39, 0xD0, 0x00, 0x69, 0x10, 0xF1, + 0x03, 0x0F, 0x35, 0xD0, 0xB3, 0xF1, 0xFF, 0x3F, 0x35, 0xD0, 0x13, 0xF1, 0x02, 0x0F, 0x32, 0xD0, + 0xB2, 0xF1, 0xFF, 0x3F, 0x2F, 0xD0, 0x12, 0xF1, 0x02, 0x0F, 0x2C, 0xD0, 0xB1, 0xF1, 0xFF, 0x3F, + 0x29, 0xD0, 0x11, 0xF1, 0x02, 0x0F, 0x26, 0xD0, 0xB0, 0xF1, 0xFF, 0x3F, 0x23, 0xD0, 0x10, 0xF1, + 0x02, 0x0F, 0x20, 0xD0, 0xDF, 0xB2, 0xD6, 0xB2, 0xCD, 0xB2, 0x04, 0x46, 0x2A, 0x46, 0x31, 0x46, + 0x38, 0x46, 0x04, 0xF0, 0x6D, 0xFA, 0x20, 0x46, 0x04, 0xF0, 0x77, 0xFA, 0xE1, 0x48, 0x04, 0xF0, + 0xEA, 0xFC, 0x03, 0x28, 0x14, 0xD0, 0x01, 0x28, 0x15, 0xD0, 0x02, 0x28, 0x13, 0xD0, 0xDD, 0x48, + 0x01, 0x68, 0x01, 0x29, 0x15, 0xD1, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0x1D, 0x03, 0xF0, 0x78, 0xBE, + 0x00, 0x21, 0x24, 0x20, 0x01, 0xE0, 0x00, 0x21, 0x25, 0x20, 0xFF, 0xF7, 0x0D, 0xFB, 0xDD, 0xE7, + 0x00, 0x21, 0x29, 0x20, 0x01, 0xE0, 0x00, 0x21, 0x2A, 0x20, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, + 0x03, 0xBB, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0xCF, 0x4F, 0x01, 0x25, 0x01, 0xAA, + 0x69, 0x46, 0x38, 0x46, 0x04, 0xF0, 0xB0, 0xFA, 0xCC, 0x4C, 0x4F, 0xF4, 0x8C, 0x56, 0x01, 0x28, + 0x03, 0xD1, 0x00, 0x98, 0xB0, 0xF5, 0x8C, 0x6F, 0x04, 0xD0, 0x00, 0x21, 0x22, 0x20, 0xFF, 0xF7, + 0xEB, 0xFA, 0x30, 0xE0, 0x32, 0x46, 0x39, 0x46, 0x20, 0x68, 0x05, 0xF0, 0x4B, 0xFD, 0x20, 0x68, + 0x04, 0xF0, 0xAD, 0xFA, 0x01, 0x28, 0x04, 0xD0, 0x00, 0x21, 0x23, 0x20, 0xFF, 0xF7, 0xDC, 0xFA, + 0x00, 0x25, 0x21, 0x68, 0x26, 0x22, 0x0F, 0x46, 0xBD, 0x48, 0x01, 0xF5, 0x86, 0x51, 0x05, 0xF0, + 0x39, 0xFD, 0x41, 0xF2, 0xE6, 0x00, 0x39, 0x18, 0xB9, 0x48, 0x36, 0x22, 0x28, 0x30, 0x05, 0xF0, + 0x31, 0xFD, 0x41, 0xF2, 0x1C, 0x10, 0x39, 0x18, 0xB5, 0x48, 0x26, 0x22, 0x48, 0x30, 0x05, 0xF0, + 0x29, 0xFD, 0x41, 0xF2, 0x42, 0x10, 0x39, 0x18, 0xB1, 0x48, 0x36, 0x22, 0x70, 0x30, 0x05, 0xF0, + 0x21, 0xFD, 0x00, 0x2D, 0x03, 0xD1, 0x31, 0x46, 0x20, 0x68, 0x05, 0xF0, 0x9A, 0xFD, 0xBD, 0xE8, + 0xFC, 0x81, 0xF8, 0xB5, 0x0D, 0x46, 0x06, 0x46, 0x00, 0x24, 0x6A, 0x46, 0x04, 0xF0, 0x64, 0xFA, + 0x01, 0x28, 0x01, 0xD0, 0x01, 0x24, 0x0B, 0xE0, 0x28, 0x68, 0x31, 0x46, 0x82, 0x00, 0xA5, 0x48, + 0x05, 0xF0, 0x4D, 0xFD, 0xA3, 0x48, 0x04, 0xF0, 0x6A, 0xFA, 0x01, 0x28, 0x00, 0xD0, 0x02, 0x24, + 0x20, 0x46, 0xF8, 0xBD, 0x2D, 0xE9, 0xF8, 0x43, 0x9E, 0x4D, 0x9F, 0x4F, 0x10, 0x35, 0x40, 0xF6, + 0xFC, 0x61, 0x9E, 0x48, 0x05, 0xF0, 0x97, 0xFD, 0x69, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xD9, 0xFF, + 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x06, 0xD0, 0xE8, 0x78, 0x01, 0x28, 0x0A, 0xD1, 0x05, 0xE0, + 0x00, 0x21, 0xA0, 0x20, 0x38, 0xE0, 0x00, 0x21, 0xA1, 0x20, 0x35, 0xE0, 0xA8, 0x78, 0x08, 0xB9, + 0x28, 0x88, 0x10, 0xB1, 0x00, 0x21, 0xA2, 0x20, 0x2E, 0xE0, 0xDF, 0xF8, 0x44, 0x82, 0xE9, 0x88, + 0xD8, 0xF8, 0x00, 0x00, 0x82, 0x8A, 0x91, 0x42, 0x02, 0xD0, 0x00, 0x21, 0xA3, 0x20, 0x05, 0xE0, + 0xA9, 0x88, 0xC0, 0x8A, 0x81, 0x42, 0x03, 0xD0, 0x00, 0x21, 0xA4, 0x20, 0xFF, 0xF7, 0x64, 0xFA, + 0x86, 0x48, 0xE9, 0x88, 0x00, 0x24, 0xA0, 0xF8, 0xF8, 0x1E, 0xA9, 0x88, 0xA0, 0xF8, 0xFA, 0x1E, + 0x00, 0x98, 0x69, 0x46, 0x07, 0xEB, 0x80, 0x07, 0x38, 0x46, 0xFF, 0xF7, 0xA2, 0xFF, 0x78, 0xB1, + 0x01, 0x28, 0x03, 0xD0, 0x00, 0x21, 0xA6, 0x20, 0xFF, 0xF7, 0x4E, 0xFA, 0xE0, 0x07, 0x24, 0xD0, + 0xA0, 0x07, 0x24, 0xD4, 0x11, 0x21, 0xA7, 0x20, 0xFF, 0xF7, 0x46, 0xFA, 0xBD, 0xE8, 0xF8, 0x83, + 0x6E, 0x78, 0x29, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x1F, 0xFE, 0x50, 0xB1, 0x10, 0x2E, 0x0B, 0xD0, + 0x11, 0x2E, 0x0C, 0xD0, 0x12, 0x2E, 0x0D, 0xD0, 0x13, 0x2E, 0xD9, 0xD1, 0x44, 0xF0, 0x10, 0x04, + 0xD6, 0xE7, 0x31, 0x46, 0xA8, 0x20, 0xDF, 0xE7, 0x44, 0xF0, 0x01, 0x04, 0xD0, 0xE7, 0x44, 0xF0, + 0x02, 0x04, 0xCD, 0xE7, 0x44, 0xF0, 0x08, 0x04, 0xCA, 0xE7, 0x10, 0x21, 0xDB, 0xE7, 0x20, 0x07, + 0x0B, 0xD4, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x50, 0x12, 0xC9, 0x07, 0x03, 0xD1, 0x90, 0xF8, + 0x80, 0x02, 0xC0, 0x07, 0x01, 0xD0, 0x12, 0x21, 0xCD, 0xE7, 0xE0, 0x06, 0xCE, 0xD4, 0x13, 0x21, + 0xC9, 0xE7, 0x38, 0xB5, 0x02, 0xF0, 0xEC, 0xFE, 0x03, 0xF0, 0x47, 0xFD, 0x00, 0x23, 0x01, 0x22, + 0x19, 0x46, 0x05, 0x20, 0x05, 0xF0, 0x12, 0xFB, 0x00, 0x23, 0x1A, 0x46, 0x01, 0x21, 0x06, 0x20, + 0x05, 0xF0, 0x0C, 0xFB, 0x03, 0x21, 0x01, 0x20, 0x00, 0xF0, 0x20, 0xF9, 0x04, 0x21, 0x07, 0x20, + 0x00, 0xF0, 0x1C, 0xF9, 0x04, 0x21, 0x08, 0x20, 0x00, 0xF0, 0x18, 0xF9, 0x50, 0x4C, 0x20, 0x68, + 0x90, 0xF8, 0xB0, 0x10, 0xC9, 0x07, 0x3B, 0xD0, 0x00, 0x25, 0x00, 0x95, 0x90, 0xF8, 0xC2, 0x00, + 0x2B, 0x46, 0xC0, 0xF3, 0x02, 0x10, 0x01, 0x22, 0x29, 0x46, 0x04, 0xF0, 0xA6, 0xFC, 0x20, 0x68, + 0x0A, 0x21, 0x90, 0xF8, 0xC2, 0x00, 0xC0, 0xF3, 0x02, 0x10, 0x04, 0xF0, 0xC6, 0xFC, 0x00, 0x95, + 0x20, 0x68, 0x00, 0x23, 0x01, 0x22, 0x90, 0xF8, 0xC2, 0x00, 0x19, 0x46, 0x00, 0xF0, 0x07, 0x00, + 0x04, 0xF0, 0x93, 0xFC, 0x20, 0x68, 0x01, 0x21, 0x90, 0xF8, 0xC2, 0x00, 0x00, 0xF0, 0x07, 0x00, + 0x04, 0xF0, 0xB3, 0xFC, 0x0D, 0x20, 0x00, 0xF0, 0xC3, 0xF8, 0x0D, 0x20, 0x00, 0xF0, 0xCB, 0xF8, + 0x07, 0x21, 0x0D, 0x20, 0x00, 0xF0, 0xD2, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0xB9, 0xF8, 0x0C, 0x20, + 0x00, 0xF0, 0xC1, 0xF8, 0xBD, 0xE8, 0x38, 0x40, 0x07, 0x21, 0x0C, 0x20, 0x00, 0xF0, 0xC6, 0xB8, + 0x38, 0xBD, 0x30, 0xB5, 0x8D, 0xB0, 0xEF, 0xF7, 0x09, 0xFA, 0x00, 0x24, 0x60, 0xB2, 0x00, 0xF0, + 0xA7, 0xF8, 0x64, 0x1C, 0x1F, 0x2C, 0xF9, 0xDB, 0xEF, 0xF7, 0xFE, 0xF9, 0x04, 0xF0, 0x96, 0xF8, + 0xFF, 0xF7, 0xCA, 0xF9, 0x04, 0xF0, 0x44, 0xFC, 0x07, 0x21, 0x0A, 0x20, 0x00, 0xF0, 0xBE, 0xF8, + 0x07, 0x21, 0x0B, 0x20, 0x00, 0xF0, 0xBA, 0xF8, 0xFE, 0xF7, 0xE0, 0xFE, 0xFE, 0xF7, 0x84, 0xFD, + 0x04, 0xA8, 0xFF, 0xF7, 0xE0, 0xF8, 0x0A, 0xA9, 0x07, 0xA8, 0xFE, 0xF7, 0x7D, 0xFF, 0x04, 0xA8, + 0x00, 0x90, 0x07, 0xA8, 0x02, 0x90, 0x0A, 0xA8, 0x03, 0x90, 0x68, 0x46, 0x04, 0xF0, 0x28, 0xFE, + 0x02, 0x21, 0x00, 0x20, 0x00, 0xF0, 0xA2, 0xF8, 0x05, 0xF0, 0x1C, 0xFD, 0x00, 0x78, 0xC0, 0x07, + 0x01, 0xD1, 0xFE, 0xF7, 0xE2, 0xFE, 0xFF, 0xF7, 0x25, 0xF9, 0xFF, 0xF7, 0x13, 0xFE, 0x04, 0xF0, + 0xAF, 0xF8, 0x10, 0x4D, 0x01, 0xAA, 0x69, 0x46, 0x28, 0x46, 0x04, 0xF0, 0x25, 0xF9, 0x0C, 0x4C, + 0x01, 0x28, 0x19, 0xD0, 0x00, 0x21, 0x20, 0x20, 0x27, 0xE0, 0x00, 0x00, 0x00, 0x90, 0xD0, 0x03, + 0x34, 0x7F, 0x10, 0x00, 0x08, 0x84, 0x10, 0x00, 0xF0, 0x9F, 0x01, 0x00, 0x24, 0x07, 0x10, 0x00, + 0xF8, 0x5B, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0xF0, 0xBF, 0x01, 0x00, 0xFC, 0x4C, 0x01, 0x20, + 0x20, 0x07, 0x10, 0x00, 0xF0, 0xEF, 0x01, 0x00, 0x00, 0x98, 0xB0, 0xF5, 0x26, 0x7F, 0xE1, 0xD1, + 0x4F, 0xF4, 0x26, 0x62, 0x29, 0x46, 0x20, 0x68, 0x05, 0xF0, 0xAC, 0xFB, 0x20, 0x68, 0x04, 0xF0, + 0x0E, 0xF9, 0x01, 0x28, 0x03, 0xD0, 0x00, 0x21, 0x21, 0x20, 0xFF, 0xF7, 0xF0, 0xF8, 0xFF, 0xF7, + 0x3A, 0xFE, 0x04, 0xF0, 0xA7, 0xFB, 0x05, 0x00, 0x2D, 0xD0, 0x01, 0x21, 0x01, 0x2D, 0x02, 0xD0, + 0x2E, 0x20, 0xFF, 0xF7, 0xE4, 0xF8, 0x20, 0x68, 0x90, 0xF8, 0x3D, 0x10, 0xA9, 0x42, 0x02, 0xD0, + 0x2F, 0x20, 0xFF, 0xF7, 0xDC, 0xF8, 0xFF, 0xF7, 0x8D, 0xFE, 0x00, 0xF0, 0x5B, 0xF8, 0xFF, 0xF7, + 0x10, 0xFF, 0x20, 0x68, 0x90, 0xF8, 0x60, 0x03, 0xC1, 0x07, 0x0F, 0xD0, 0x81, 0x07, 0x0D, 0xD5, + 0x00, 0x21, 0x01, 0x23, 0x40, 0x09, 0x1A, 0x46, 0x00, 0x91, 0x04, 0xF0, 0xD6, 0xFB, 0x20, 0x68, + 0x00, 0x21, 0x90, 0xF8, 0x60, 0x03, 0x40, 0x09, 0x04, 0xF0, 0xF7, 0xFB, 0x0D, 0xB0, 0xBD, 0xE8, + 0x30, 0x40, 0xFF, 0xF7, 0x9F, 0xB8, 0x00, 0x21, 0x2D, 0x20, 0xFF, 0xF7, 0x05, 0xF9, 0xDA, 0xE7, + 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, + 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, + 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0x49, 0x07, 0x09, 0x0E, + 0x00, 0x28, 0x06, 0xDA, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0x80, 0xF8, 0x14, 0x1D, + 0x70, 0x47, 0x00, 0xF1, 0xE0, 0x20, 0x80, 0xF8, 0x00, 0x14, 0x70, 0x47, 0x70, 0xB5, 0x0D, 0x46, + 0x04, 0x46, 0xFF, 0xF7, 0xE0, 0xFF, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xE7, 0xFF, 0x04, 0xF0, + 0x1F, 0x01, 0x01, 0x20, 0x88, 0x40, 0x61, 0x09, 0x89, 0x00, 0x01, 0xF1, 0xE0, 0x21, 0xC1, 0xF8, + 0x00, 0x01, 0x70, 0xBD, 0x10, 0xB5, 0x04, 0xF0, 0x2B, 0xFE, 0x00, 0x23, 0x01, 0x22, 0x19, 0x46, + 0x18, 0x46, 0x05, 0xF0, 0xCB, 0xF9, 0x00, 0x23, 0x01, 0x22, 0x19, 0x46, 0x10, 0x46, 0x05, 0xF0, + 0xC5, 0xF9, 0x00, 0x23, 0x1A, 0x46, 0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0xBF, 0xF9, 0x00, 0x23, + 0x1A, 0x46, 0x01, 0x21, 0x03, 0x20, 0x05, 0xF0, 0xB9, 0xF9, 0x00, 0x23, 0x1A, 0x46, 0x01, 0x21, + 0x04, 0x20, 0x05, 0xF0, 0xB3, 0xF9, 0x17, 0x48, 0x00, 0x68, 0x01, 0x7C, 0xA5, 0x29, 0x08, 0xD0, + 0x4F, 0xF4, 0xFA, 0x40, 0x05, 0xF0, 0x94, 0xF9, 0x00, 0x21, 0x28, 0x20, 0xFF, 0xF7, 0x9C, 0xF8, + 0x02, 0xE0, 0x40, 0x69, 0x05, 0xF0, 0x8C, 0xF9, 0x04, 0x21, 0x02, 0x20, 0xFF, 0xF7, 0xB6, 0xFF, + 0x04, 0x21, 0x03, 0x20, 0xFF, 0xF7, 0xB2, 0xFF, 0x04, 0x21, 0x08, 0x46, 0xFF, 0xF7, 0xAE, 0xFF, + 0x04, 0x21, 0x05, 0x20, 0xFF, 0xF7, 0xAA, 0xFF, 0x04, 0x21, 0x06, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, + 0x01, 0x21, 0x09, 0x20, 0xFF, 0xF7, 0xA2, 0xFF, 0x04, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x0F, 0x20, + 0x9C, 0xE7, 0x00, 0x00, 0x24, 0x07, 0x10, 0x00, 0x88, 0x42, 0x00, 0xD3, 0x08, 0x46, 0x90, 0x42, + 0x00, 0xD3, 0x10, 0x46, 0x70, 0x47, 0x88, 0x42, 0x00, 0xD8, 0x08, 0x46, 0x90, 0x42, 0x00, 0xD8, + 0x10, 0x46, 0x70, 0x47, 0x88, 0x42, 0x00, 0xD3, 0x08, 0x46, 0x70, 0x47, 0x88, 0x42, 0x00, 0xD8, + 0x08, 0x46, 0x70, 0x47, 0x02, 0x46, 0x00, 0x20, 0x4F, 0xF0, 0x80, 0x41, 0x00, 0xE0, 0x89, 0x08, + 0x91, 0x42, 0xFC, 0xD8, 0x07, 0xE0, 0x43, 0x18, 0x93, 0x42, 0x02, 0xD8, 0xD2, 0x1A, 0x00, 0xEB, + 0x41, 0x00, 0x40, 0x08, 0x89, 0x08, 0x00, 0x29, 0xF5, 0xD1, 0x82, 0x42, 0x00, 0xD9, 0x40, 0x1C, + 0x70, 0x47, 0x10, 0xB5, 0x5A, 0x43, 0x02, 0x9C, 0x06, 0xE0, 0x00, 0xBF, 0x50, 0xF8, 0x22, 0x30, + 0x93, 0xFB, 0xF4, 0xF3, 0x41, 0xF8, 0x22, 0x30, 0x52, 0x1E, 0xF7, 0xD2, 0x10, 0xBD, 0x10, 0xB5, + 0x5A, 0x43, 0x02, 0x9C, 0x05, 0xE0, 0x00, 0xBF, 0x50, 0xF8, 0x22, 0x30, 0x63, 0x43, 0x41, 0xF8, + 0x22, 0x30, 0x52, 0x1E, 0xF8, 0xD2, 0x10, 0xBD, 0x30, 0xB5, 0x03, 0x9C, 0x63, 0x43, 0x06, 0xE0, + 0x50, 0xF8, 0x23, 0x40, 0x51, 0xF8, 0x23, 0x50, 0x2C, 0x44, 0x42, 0xF8, 0x23, 0x40, 0x5B, 0x1E, + 0xF6, 0xD2, 0x30, 0xBD, 0x30, 0xB5, 0x03, 0x9C, 0x63, 0x43, 0x06, 0xE0, 0x50, 0xF8, 0x23, 0x40, + 0x51, 0xF8, 0x23, 0x50, 0x64, 0x1B, 0x42, 0xF8, 0x23, 0x40, 0x5B, 0x1E, 0xF6, 0xD2, 0x30, 0xBD, + 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0x46, 0xDD, 0xE9, 0x09, 0x06, 0xDD, 0xF8, 0x34, 0xE0, 0x8A, 0x46, + 0x82, 0x42, 0x26, 0xD1, 0x00, 0x20, 0x22, 0xE0, 0x00, 0xFB, 0x02, 0xF1, 0x0B, 0xEB, 0x81, 0x09, + 0x0B, 0x9D, 0x00, 0xFB, 0x0E, 0xF1, 0x00, 0x24, 0x05, 0xEB, 0x81, 0x05, 0x14, 0xE0, 0x00, 0x21, + 0x0F, 0xE0, 0x00, 0xBF, 0x01, 0xFB, 0x06, 0xF8, 0x03, 0xEB, 0x88, 0x08, 0x59, 0xF8, 0x21, 0xC0, + 0x55, 0xF8, 0x24, 0x70, 0x58, 0xF8, 0x24, 0x80, 0x49, 0x1C, 0x0C, 0xFB, 0x08, 0x77, 0x45, 0xF8, + 0x24, 0x70, 0x91, 0x42, 0xEE, 0xDB, 0x64, 0x1C, 0xB4, 0x42, 0xE8, 0xDB, 0x40, 0x1C, 0x50, 0x45, + 0xDA, 0xDB, 0xBD, 0xE8, 0xF0, 0x8F, 0x10, 0xB5, 0x00, 0x23, 0x1C, 0x46, 0x42, 0xB1, 0x02, 0x78, + 0x52, 0x1C, 0xD2, 0xB2, 0x02, 0x70, 0x8A, 0x42, 0x03, 0xD9, 0x04, 0x70, 0x01, 0x23, 0x00, 0xE0, + 0x04, 0x70, 0x18, 0x46, 0x10, 0xBD, 0x30, 0xB5, 0x00, 0x24, 0x01, 0x23, 0x05, 0xE0, 0x0C, 0x44, + 0xE4, 0x1C, 0x04, 0xF0, 0x03, 0x05, 0x64, 0x1B, 0x5B, 0x1C, 0x93, 0x42, 0xF7, 0xDD, 0x00, 0xEB, + 0x44, 0x00, 0x30, 0xBD, 0x70, 0xB5, 0x05, 0x46, 0x18, 0x46, 0x00, 0x24, 0x0E, 0xE0, 0x2B, 0x5D, + 0x58, 0x40, 0x08, 0x23, 0x06, 0x06, 0x02, 0xD5, 0x82, 0xEA, 0x40, 0x00, 0x00, 0xE0, 0x40, 0x00, + 0x5B, 0x1E, 0xC0, 0xB2, 0x13, 0xF0, 0xFF, 0x03, 0xF4, 0xD1, 0x64, 0x1C, 0x8C, 0x42, 0xEE, 0xD3, + 0x70, 0xBD, 0x00, 0x00, 0x88, 0x42, 0x01, 0xDD, 0x08, 0x46, 0x70, 0x47, 0x00, 0x28, 0xFC, 0xDA, + 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x04, 0xE0, 0x00, 0xEB, 0x82, 0x03, 0x53, 0xF8, 0x04, 0x4C, + 0x1C, 0x60, 0x52, 0x1E, 0xF8, 0xD1, 0x09, 0x68, 0x01, 0x60, 0x10, 0xBD, 0x10, 0xB5, 0x03, 0xE0, + 0x00, 0xEB, 0x82, 0x03, 0x0C, 0x68, 0x1C, 0x60, 0x52, 0x1E, 0xF9, 0xD2, 0x10, 0xBD, 0x30, 0xB5, + 0x06, 0xE0, 0x00, 0xBF, 0x00, 0xEB, 0xC2, 0x03, 0x73, 0xE9, 0x02, 0x45, 0xC3, 0xE9, 0x02, 0x45, + 0x52, 0x1E, 0xF7, 0xD1, 0xD1, 0xE9, 0x00, 0x21, 0xC0, 0xE9, 0x00, 0x21, 0x30, 0xBD, 0x10, 0xB5, + 0x53, 0x88, 0x4C, 0x88, 0x1B, 0x1B, 0x43, 0x80, 0x12, 0x88, 0x09, 0x88, 0x51, 0x1A, 0x01, 0x80, + 0x10, 0xBD, 0x08, 0xB5, 0x0A, 0x46, 0x01, 0x46, 0x68, 0x46, 0xFF, 0xF7, 0xF0, 0xFF, 0xBD, 0xF9, + 0x00, 0x10, 0xBD, 0xF9, 0x02, 0x00, 0x49, 0x43, 0x00, 0xFB, 0x00, 0x10, 0x08, 0xBD, 0x10, 0xB5, + 0x88, 0x42, 0x02, 0x9C, 0x01, 0xDC, 0x20, 0x46, 0x10, 0xBD, 0x90, 0x42, 0x01, 0xDB, 0x18, 0x46, + 0x10, 0xBD, 0x8A, 0x42, 0x00, 0xD1, 0x52, 0x1C, 0x40, 0x1A, 0xE3, 0x1A, 0x58, 0x43, 0x51, 0x1A, + 0x90, 0xFB, 0xF1, 0xF0, 0x20, 0x1A, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x2A, 0x03, 0xD0, 0x43, 0x1A, + 0x93, 0x42, 0x01, 0xDD, 0x88, 0x18, 0x10, 0xBD, 0x54, 0x42, 0xA3, 0x42, 0xFB, 0xDA, 0x88, 0x1A, + 0x10, 0xBD, 0x91, 0x42, 0x01, 0xD1, 0x00, 0xB2, 0x70, 0x47, 0x50, 0x43, 0xB0, 0xFB, 0xF1, 0xF0, + 0x00, 0xB2, 0x90, 0x42, 0xF7, 0xD9, 0x10, 0x46, 0xF5, 0xE7, 0x70, 0xB5, 0x0B, 0x00, 0x02, 0x46, + 0x3D, 0xD0, 0x1F, 0x4C, 0x20, 0x68, 0x46, 0x8E, 0x85, 0x8E, 0xB2, 0xF9, 0x02, 0x00, 0x31, 0xB2, + 0xFF, 0xF7, 0x80, 0xFF, 0x58, 0x80, 0xB2, 0xF9, 0x00, 0x00, 0x29, 0xB2, 0xFF, 0xF7, 0x7A, 0xFF, + 0x18, 0x80, 0x21, 0x68, 0x91, 0xF8, 0x36, 0x10, 0x49, 0x07, 0x02, 0xD5, 0x59, 0x88, 0x71, 0x1A, + 0x59, 0x80, 0x21, 0x68, 0x91, 0xF8, 0x36, 0x10, 0x89, 0x07, 0x01, 0xD5, 0x28, 0x1A, 0x18, 0x80, + 0x20, 0x68, 0x90, 0xF8, 0x36, 0x10, 0x09, 0x07, 0x10, 0xD5, 0xB0, 0xF8, 0x37, 0x20, 0xB3, 0xF9, + 0x02, 0x00, 0x31, 0x46, 0xFF, 0xF7, 0xC5, 0xFF, 0x58, 0x80, 0x20, 0x68, 0x29, 0x46, 0xB0, 0xF8, + 0x39, 0x20, 0xB3, 0xF9, 0x00, 0x00, 0xFF, 0xF7, 0xBC, 0xFF, 0x18, 0x80, 0x20, 0x68, 0x90, 0xF8, + 0x36, 0x00, 0xC0, 0x07, 0x03, 0xD0, 0x58, 0x88, 0x19, 0x88, 0x59, 0x80, 0x18, 0x80, 0x70, 0xBD, + 0x20, 0x07, 0x10, 0x00, 0x73, 0xB5, 0x1D, 0x24, 0xDD, 0xE9, 0x00, 0x56, 0x22, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x05, 0xF0, 0x18, 0xF9, 0x28, 0x40, 0x31, 0x40, 0x08, 0x43, 0x01, 0xD1, 0x64, 0x1E, + 0xF4, 0xD5, 0x08, 0x21, 0x68, 0x46, 0x03, 0xF0, 0x85, 0xFE, 0xFF, 0x49, 0xC0, 0xB2, 0x09, 0x68, + 0x91, 0xF8, 0xE7, 0x10, 0xC1, 0xF3, 0x41, 0x11, 0x02, 0x29, 0x0E, 0xD3, 0x10, 0xF0, 0x03, 0x00, + 0x05, 0xD0, 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x1F, 0x20, 0x0A, 0xE0, 0x0F, 0x20, + 0x08, 0xE0, 0x7F, 0x20, 0x06, 0xE0, 0x3F, 0x20, 0x04, 0xE0, 0xC0, 0x07, 0x01, 0xD0, 0x07, 0x20, + 0x00, 0xE0, 0x03, 0x20, 0x00, 0x21, 0x62, 0x1C, 0x05, 0xF0, 0xED, 0xF8, 0xDD, 0xE9, 0x00, 0x23, + 0x10, 0x43, 0x19, 0x43, 0xCD, 0xE9, 0x00, 0x01, 0x7C, 0xBD, 0x10, 0xB5, 0xEB, 0x4C, 0x50, 0x28, + 0x14, 0xD0, 0x08, 0xDC, 0x10, 0x28, 0x11, 0xD0, 0x11, 0x28, 0x25, 0xD0, 0x12, 0x28, 0x23, 0xD0, + 0x13, 0x28, 0x06, 0xD1, 0x20, 0xE0, 0x51, 0x28, 0x1E, 0xD0, 0x52, 0x28, 0x1C, 0xD0, 0x53, 0x28, + 0x1A, 0xD0, 0x00, 0x20, 0xC4, 0xE9, 0x02, 0x00, 0x01, 0x46, 0x1B, 0xE0, 0x02, 0xF0, 0x5D, 0xFC, + 0xC4, 0xE9, 0x02, 0x01, 0x02, 0xF0, 0x5B, 0xFC, 0xC4, 0xE9, 0x04, 0x01, 0xDA, 0x48, 0x00, 0x68, + 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x0E, 0xD0, 0xD4, 0xE9, 0x02, 0x01, 0xFF, 0xF7, + 0x99, 0xFF, 0xC4, 0xE9, 0x02, 0x01, 0x07, 0xE0, 0x02, 0xF0, 0x47, 0xFC, 0xC4, 0xE9, 0x02, 0x01, + 0x02, 0xF0, 0x45, 0xFC, 0xC4, 0xE9, 0x04, 0x01, 0xD0, 0x48, 0x08, 0x21, 0x08, 0x30, 0x03, 0xF0, + 0x21, 0xFE, 0x20, 0x60, 0xCD, 0x48, 0x08, 0x21, 0x10, 0x30, 0x03, 0xF0, 0x1B, 0xFE, 0x60, 0x60, + 0x10, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x08, 0x21, 0xDD, 0xE9, 0x0F, 0xBA, 0x68, 0x46, 0x03, 0xF0, + 0x11, 0xFE, 0x81, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x03, 0xF0, 0x0C, 0xFE, 0x07, 0x46, 0x00, 0x24, + 0x20, 0x46, 0x3A, 0xE0, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, 0x05, 0xF0, 0x8C, 0xF8, 0xDD, 0xE9, + 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x2D, 0xD0, 0x00, 0x25, 0x2E, 0x46, 0x27, 0xE0, + 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x05, 0xF0, 0x7E, 0xF8, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, + 0x19, 0x40, 0x08, 0x43, 0x1B, 0xD0, 0x11, 0x98, 0x60, 0xB1, 0x04, 0xFB, 0x07, 0xF0, 0x0B, 0xEB, + 0x05, 0x01, 0x41, 0x56, 0x32, 0x46, 0x01, 0xEB, 0x0A, 0x03, 0x21, 0x46, 0x0E, 0x98, 0x03, 0xF0, + 0x5C, 0xFA, 0x0B, 0xE0, 0x32, 0x46, 0x21, 0x46, 0x0E, 0x98, 0x03, 0xF0, 0x4B, 0xFA, 0x04, 0xFB, + 0x07, 0xF1, 0x0B, 0xEB, 0x05, 0x02, 0xA0, 0xEB, 0x0A, 0x00, 0x88, 0x54, 0x6D, 0x1C, 0x76, 0x1C, + 0xBD, 0x42, 0xD5, 0xDB, 0x64, 0x1C, 0x08, 0xF1, 0x01, 0x00, 0x80, 0x46, 0x4C, 0x45, 0xC1, 0xDB, + 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xFF, 0x5F, 0x84, 0xB0, 0x08, 0x21, 0xDD, 0xE9, 0x12, 0xAB, + 0x04, 0xA8, 0x03, 0xF0, 0xBF, 0xFD, 0x81, 0x46, 0x08, 0x21, 0x06, 0xA8, 0x03, 0xF0, 0xBA, 0xFD, + 0x80, 0x46, 0x00, 0x25, 0x0A, 0xF1, 0x48, 0x00, 0x02, 0x90, 0x20, 0x30, 0x01, 0x90, 0x48, 0x38, + 0x2C, 0x46, 0x2F, 0x46, 0x2E, 0x46, 0x00, 0x90, 0x34, 0xE0, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x05, 0xF0, 0x31, 0xF8, 0xDD, 0xE9, 0x04, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x27, 0xD0, + 0x16, 0x98, 0x90, 0xB1, 0x1B, 0xF8, 0x05, 0x10, 0x14, 0x98, 0x08, 0x44, 0xC2, 0xB2, 0x39, 0x46, + 0x02, 0x98, 0x03, 0xF0, 0x7E, 0xFA, 0x05, 0xEB, 0x09, 0x01, 0x41, 0x44, 0x1B, 0xF9, 0x01, 0x20, + 0x39, 0x46, 0x50, 0x46, 0x03, 0xF0, 0x4D, 0xFA, 0x10, 0xE0, 0x39, 0x46, 0x02, 0x98, 0x03, 0xF0, + 0x6E, 0xFA, 0x14, 0x99, 0x40, 0x1A, 0x0B, 0xF8, 0x05, 0x00, 0x39, 0x46, 0x50, 0x46, 0x03, 0xF0, + 0x39, 0xFA, 0x05, 0xEB, 0x09, 0x02, 0x42, 0x44, 0x0B, 0xF8, 0x02, 0x00, 0x6D, 0x1C, 0xED, 0xB2, + 0x7F, 0x1C, 0xFF, 0xB2, 0x4D, 0x45, 0xC8, 0xDB, 0x38, 0xE0, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x04, 0xF0, 0xF9, 0xFF, 0xDD, 0xE9, 0x06, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x2B, 0xD0, + 0x16, 0x98, 0xA0, 0xB1, 0x04, 0xEB, 0x09, 0x01, 0x15, 0x98, 0x1B, 0xF8, 0x01, 0x10, 0x08, 0x44, + 0xC2, 0xB2, 0x31, 0x46, 0x01, 0x98, 0x03, 0xF0, 0x44, 0xFA, 0x04, 0xEB, 0x49, 0x01, 0x41, 0x44, + 0x1B, 0xF9, 0x01, 0x20, 0x31, 0x46, 0x00, 0x98, 0x03, 0xF0, 0x13, 0xFA, 0x12, 0xE0, 0x31, 0x46, + 0x01, 0x98, 0x03, 0xF0, 0x34, 0xFA, 0x15, 0x99, 0x04, 0xEB, 0x09, 0x02, 0x40, 0x1A, 0x0B, 0xF8, + 0x02, 0x00, 0x31, 0x46, 0x00, 0x98, 0x03, 0xF0, 0xFD, 0xF9, 0x04, 0xEB, 0x49, 0x02, 0x42, 0x44, + 0x0B, 0xF8, 0x02, 0x00, 0x64, 0x1C, 0xE4, 0xB2, 0x76, 0x1C, 0xF6, 0xB2, 0x44, 0x45, 0xC4, 0xDB, + 0x08, 0xB0, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFF, 0x5F, 0x08, 0x21, 0xDD, 0xE9, 0x0E, 0xBA, + 0x68, 0x46, 0x03, 0xF0, 0x2F, 0xFD, 0x81, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x03, 0xF0, 0x2A, 0xFD, + 0x07, 0x46, 0x00, 0x24, 0x20, 0x46, 0x29, 0xE0, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, 0x04, 0xF0, + 0xAA, 0xFF, 0xDD, 0xE9, 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x1C, 0xD0, 0x00, 0x25, + 0x2E, 0x46, 0x16, 0xE0, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x04, 0xF0, 0x9C, 0xFF, 0xDD, 0xE9, + 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x0A, 0xD0, 0x32, 0x46, 0x21, 0x46, 0x58, 0x46, + 0x03, 0xF0, 0x78, 0xF9, 0x04, 0xFB, 0x07, 0x52, 0x80, 0x00, 0x2A, 0xF8, 0x12, 0x00, 0x6D, 0x1C, + 0x76, 0x1C, 0xBD, 0x42, 0xE6, 0xDB, 0x64, 0x1C, 0x08, 0xF1, 0x01, 0x00, 0x80, 0x46, 0x4C, 0x45, + 0xD2, 0xDB, 0x2D, 0xE7, 0x2D, 0xE9, 0xFF, 0x5F, 0x08, 0x21, 0xDD, 0xE9, 0x0E, 0x9B, 0x68, 0x46, + 0x03, 0xF0, 0xF0, 0xFC, 0x82, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x03, 0xF0, 0xEB, 0xFC, 0x00, 0x25, + 0x80, 0x46, 0x2C, 0x46, 0x2F, 0x46, 0x2E, 0x46, 0x3D, 0xE0, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x04, 0xF0, 0x69, 0xFF, 0xDD, 0xE9, 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x30, 0xD0, + 0x39, 0x46, 0x09, 0xF1, 0x48, 0x00, 0x03, 0xF0, 0xBA, 0xF9, 0x27, 0x49, 0x99, 0xF8, 0x92, 0xC0, + 0x0A, 0x68, 0x92, 0xF8, 0x43, 0x31, 0x92, 0xF8, 0x42, 0x21, 0x03, 0xF0, 0x0F, 0x01, 0x49, 0x1C, + 0x0C, 0xFB, 0x01, 0xFC, 0x01, 0x21, 0x01, 0xEB, 0x13, 0x13, 0x00, 0xFB, 0x03, 0xC3, 0x99, 0xF8, + 0x90, 0x00, 0x01, 0xEB, 0x12, 0x11, 0x00, 0xFB, 0x01, 0x30, 0x10, 0x99, 0x19, 0xB9, 0x4F, 0xF6, + 0xFF, 0x71, 0x01, 0xEA, 0x80, 0x00, 0x2B, 0xF8, 0x15, 0x00, 0x39, 0x46, 0x48, 0x46, 0x03, 0xF0, + 0x69, 0xF9, 0x05, 0xEB, 0x0A, 0x02, 0x80, 0x00, 0x42, 0x44, 0x6D, 0x1C, 0x2B, 0xF8, 0x12, 0x00, + 0xED, 0xB2, 0x7F, 0x1C, 0xFF, 0xB2, 0x55, 0x45, 0xBF, 0xDB, 0x44, 0xE0, 0x32, 0x46, 0x01, 0x20, + 0x00, 0x21, 0x04, 0xF0, 0x28, 0xFF, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, + 0x37, 0xD0, 0x31, 0x46, 0x09, 0xF1, 0x68, 0x00, 0x03, 0xF0, 0x79, 0xF9, 0x06, 0x49, 0x99, 0xF8, + 0x93, 0x50, 0x0B, 0x68, 0x93, 0xF8, 0x48, 0x11, 0x01, 0xF0, 0x0F, 0x02, 0x52, 0x1C, 0x55, 0x43, + 0x01, 0x22, 0x02, 0xEB, 0x11, 0x11, 0x03, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x70, 0x07, 0x10, 0x00, + 0x00, 0xFB, 0x01, 0x51, 0x93, 0xF8, 0x47, 0x31, 0x99, 0xF8, 0x91, 0x00, 0x02, 0xEB, 0x13, 0x12, + 0x00, 0xFB, 0x02, 0x10, 0x10, 0x99, 0x19, 0xB9, 0x4F, 0xF6, 0xFF, 0x71, 0x01, 0xEA, 0x80, 0x00, + 0x04, 0xEB, 0x0A, 0x02, 0x31, 0x46, 0x2B, 0xF8, 0x12, 0x00, 0x09, 0xF1, 0x20, 0x00, 0x03, 0xF0, + 0x21, 0xF9, 0x04, 0xEB, 0x4A, 0x02, 0x80, 0x00, 0x42, 0x44, 0x64, 0x1C, 0x2B, 0xF8, 0x12, 0x00, + 0xE4, 0xB2, 0x76, 0x1C, 0xF6, 0xB2, 0x44, 0x45, 0xB8, 0xDB, 0x91, 0xE6, 0x2D, 0xE9, 0xF0, 0x43, + 0x89, 0x46, 0x00, 0x27, 0x85, 0xB0, 0x90, 0x46, 0x04, 0x46, 0x3E, 0x46, 0xFC, 0x21, 0x04, 0xF0, + 0x90, 0xFF, 0xFE, 0x4D, 0xB8, 0xF1, 0x01, 0x0F, 0x28, 0x78, 0x20, 0x71, 0x28, 0x79, 0x60, 0x71, + 0xFB, 0x48, 0x90, 0xF8, 0x82, 0x1B, 0xA1, 0x71, 0x90, 0xF8, 0x83, 0x1B, 0xE1, 0x71, 0x90, 0xF8, + 0x84, 0x1B, 0xA1, 0x72, 0x90, 0xF8, 0x85, 0x1B, 0xE1, 0x72, 0x90, 0xF8, 0x80, 0x1B, 0x21, 0x73, + 0x90, 0xF8, 0x81, 0x0B, 0x60, 0x73, 0x08, 0xD1, 0xF2, 0x48, 0x00, 0x68, 0x81, 0x7F, 0xA5, 0x29, + 0x03, 0xD1, 0x90, 0xF9, 0x1F, 0x70, 0x90, 0xF9, 0x20, 0x60, 0x04, 0xF1, 0x10, 0x00, 0xCD, 0xE9, + 0x01, 0x07, 0xED, 0x48, 0x00, 0x90, 0x00, 0x21, 0xCD, 0xE9, 0x03, 0x61, 0x05, 0xF1, 0x08, 0x00, + 0x0F, 0xC8, 0xFF, 0xF7, 0x57, 0xFE, 0xA5, 0x20, 0x20, 0x70, 0x12, 0x20, 0x60, 0x70, 0xA4, 0xF8, + 0x02, 0x90, 0xD5, 0xE9, 0x00, 0x01, 0x08, 0x44, 0x13, 0x30, 0x80, 0x08, 0x05, 0xB0, 0xBD, 0xE8, + 0xF0, 0x83, 0x2D, 0xE9, 0xF0, 0x43, 0x89, 0x46, 0x00, 0x27, 0x85, 0xB0, 0x90, 0x46, 0x04, 0x46, + 0x3E, 0x46, 0xFC, 0x21, 0x04, 0xF0, 0x45, 0xFF, 0xD8, 0x4D, 0xB8, 0xF1, 0x01, 0x0F, 0x28, 0x78, + 0x20, 0x71, 0x28, 0x79, 0x60, 0x71, 0xD6, 0x48, 0x90, 0xF8, 0x1A, 0x1C, 0xA1, 0x71, 0x90, 0xF8, + 0x1B, 0x1C, 0xE1, 0x71, 0x90, 0xF8, 0x1C, 0x1C, 0xA1, 0x72, 0x90, 0xF8, 0x1D, 0x1C, 0xE1, 0x72, + 0x90, 0xF8, 0x18, 0x1C, 0x21, 0x73, 0x90, 0xF8, 0x19, 0x0C, 0x60, 0x73, 0x09, 0xD1, 0xCD, 0x48, + 0x00, 0x68, 0x90, 0xF8, 0x21, 0x10, 0xA5, 0x29, 0x03, 0xD1, 0x10, 0xF9, 0x22, 0x7F, 0x90, 0xF9, + 0x01, 0x60, 0x04, 0xF1, 0x10, 0x00, 0xCD, 0xE9, 0x01, 0x07, 0xC7, 0x48, 0x00, 0x21, 0x98, 0x30, + 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x61, 0x05, 0xF1, 0x08, 0x00, 0x0F, 0xC8, 0xFF, 0xF7, 0x0A, 0xFE, + 0xA5, 0x20, 0x20, 0x70, 0x13, 0x20, 0x60, 0x70, 0xA4, 0xF8, 0x02, 0x90, 0xD5, 0xE9, 0x00, 0x01, + 0x08, 0x44, 0x13, 0x30, 0x80, 0x08, 0xB1, 0xE7, 0x70, 0xB5, 0x0E, 0x46, 0x04, 0x46, 0x00, 0x25, + 0xFF, 0xF7, 0x63, 0xFD, 0x10, 0x2C, 0x06, 0xD0, 0x11, 0x2C, 0x08, 0xD0, 0x12, 0x2C, 0x0C, 0xD0, + 0x13, 0x2C, 0x08, 0xD1, 0x0D, 0xE0, 0x30, 0x46, 0x00, 0xF0, 0x7D, 0xF8, 0x02, 0xE0, 0x30, 0x46, + 0x00, 0xF0, 0x9C, 0xF8, 0x05, 0x46, 0x28, 0x46, 0x70, 0xBD, 0x30, 0x46, 0x00, 0xF0, 0xB8, 0xF8, + 0xF8, 0xE7, 0x30, 0x46, 0x00, 0xF0, 0xEE, 0xF8, 0xF4, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x1E, 0x46, + 0x17, 0x46, 0x88, 0x46, 0x05, 0x46, 0x00, 0x24, 0xFF, 0xF7, 0x3F, 0xFD, 0x10, 0x2D, 0x06, 0xD0, + 0x11, 0x2D, 0x0A, 0xD0, 0x12, 0x2D, 0x11, 0xD0, 0x13, 0x2D, 0x0C, 0xD1, 0x14, 0xE0, 0x32, 0x46, + 0x39, 0x46, 0x40, 0x46, 0x00, 0xF0, 0x11, 0xF9, 0x04, 0xE0, 0x32, 0x46, 0x39, 0x46, 0x40, 0x46, + 0x00, 0xF0, 0x4A, 0xF9, 0x04, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x32, 0x46, 0x39, 0x46, + 0x40, 0x46, 0xFF, 0xF7, 0x23, 0xFF, 0xF5, 0xE7, 0x32, 0x46, 0x39, 0x46, 0x40, 0x46, 0xFF, 0xF7, + 0x68, 0xFF, 0xEF, 0xE7, 0xFE, 0xB5, 0x17, 0x46, 0x06, 0x46, 0x0D, 0x46, 0xFF, 0xF7, 0x15, 0xFD, + 0x8E, 0x48, 0x05, 0xF1, 0x10, 0x04, 0x50, 0x2E, 0x01, 0x78, 0x29, 0x71, 0x01, 0x79, 0x69, 0x71, + 0x07, 0xD0, 0x51, 0x2E, 0x07, 0xD0, 0x8D, 0x49, 0x52, 0x2E, 0x0F, 0xD0, 0x53, 0x2E, 0x25, 0xD1, + 0x13, 0xE0, 0x87, 0x49, 0x00, 0xE0, 0x8A, 0x49, 0xCD, 0xE9, 0x00, 0x14, 0x84, 0x68, 0x0C, 0x30, + 0x90, 0xE8, 0x0E, 0x00, 0x20, 0x46, 0xFF, 0xF7, 0x1E, 0xFE, 0x17, 0xE0, 0x09, 0x68, 0x82, 0x4A, + 0x91, 0xF8, 0x42, 0x11, 0x01, 0xF0, 0x01, 0x01, 0x06, 0xE0, 0x09, 0x68, 0x7E, 0x4A, 0x91, 0xF8, + 0x92, 0x19, 0x98, 0x32, 0x01, 0xF0, 0x01, 0x01, 0x00, 0x92, 0xCD, 0xE9, 0x01, 0x41, 0x84, 0x68, + 0x0C, 0x30, 0x90, 0xE8, 0x0E, 0x00, 0x20, 0x46, 0xFF, 0xF7, 0x44, 0xFE, 0xA5, 0x20, 0x28, 0x70, + 0x6E, 0x70, 0x6F, 0x80, 0xFE, 0xBD, 0x1F, 0xB5, 0x70, 0x49, 0x02, 0x79, 0x0B, 0x68, 0x9A, 0x42, + 0x03, 0xD1, 0x42, 0x79, 0x4B, 0x68, 0x9A, 0x42, 0x02, 0xD0, 0x00, 0x20, 0x04, 0xB0, 0x10, 0xBD, + 0x6C, 0x4B, 0x00, 0x22, 0x1B, 0x68, 0x9C, 0x7E, 0xA5, 0x2C, 0x01, 0xD1, 0x93, 0xF9, 0x1B, 0x20, + 0x67, 0x4C, 0x0D, 0xF1, 0x04, 0x0C, 0x01, 0x23, 0x10, 0x30, 0x00, 0x94, 0x8C, 0xE8, 0x0D, 0x00, + 0x08, 0x31, 0x0F, 0xC9, 0xFF, 0xF7, 0xFD, 0xFC, 0x01, 0x20, 0xE7, 0xE7, 0x1F, 0xB5, 0x5F, 0x49, + 0x02, 0x79, 0x0B, 0x68, 0x9A, 0x42, 0x03, 0xD1, 0x42, 0x79, 0x4B, 0x68, 0x9A, 0x42, 0x01, 0xD0, + 0x00, 0x20, 0xDB, 0xE7, 0x5B, 0x4B, 0x00, 0x22, 0x1B, 0x68, 0x1C, 0x7F, 0xA5, 0x2C, 0x01, 0xD1, + 0x93, 0xF9, 0x1D, 0x20, 0x5A, 0x4B, 0x0D, 0xF1, 0x04, 0x0C, 0x01, 0x24, 0x10, 0x30, 0x00, 0x93, + 0x8C, 0xE8, 0x15, 0x00, 0x08, 0x31, 0x0F, 0xC9, 0xFF, 0xF7, 0xDB, 0xFC, 0x01, 0x20, 0xC5, 0xE7, + 0x30, 0xB5, 0x4E, 0x49, 0x02, 0x79, 0x85, 0xB0, 0x0B, 0x68, 0x9A, 0x42, 0x03, 0xD1, 0x42, 0x79, + 0x4B, 0x68, 0x9A, 0x42, 0x02, 0xD0, 0x00, 0x20, 0x05, 0xB0, 0x30, 0xBD, 0x48, 0x4A, 0x85, 0x79, + 0x00, 0x24, 0x82, 0xF8, 0x82, 0x5B, 0xC5, 0x79, 0x82, 0xF8, 0x83, 0x5B, 0x85, 0x7A, 0x82, 0xF8, + 0x84, 0x5B, 0xC5, 0x7A, 0x82, 0xF8, 0x85, 0x5B, 0x05, 0x7B, 0x82, 0xF8, 0x80, 0x5B, 0x45, 0x7B, + 0x82, 0xF8, 0x81, 0x5B, 0x3F, 0x4A, 0x23, 0x46, 0x12, 0x68, 0x95, 0x7F, 0xA5, 0x2D, 0x03, 0xD1, + 0x92, 0xF9, 0x1F, 0x40, 0x92, 0xF9, 0x20, 0x30, 0x10, 0x30, 0xCD, 0xE9, 0x01, 0x04, 0x3A, 0x48, + 0x01, 0x22, 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x32, 0x08, 0x31, 0x0F, 0xC9, 0xFF, 0xF7, 0xF2, 0xFC, + 0x01, 0x20, 0xD1, 0xE7, 0x30, 0xB5, 0x31, 0x49, 0x02, 0x79, 0x85, 0xB0, 0x0B, 0x68, 0x9A, 0x42, + 0x03, 0xD1, 0x42, 0x79, 0x4B, 0x68, 0x9A, 0x42, 0x01, 0xD0, 0x00, 0x20, 0xC4, 0xE7, 0x2C, 0x4A, + 0x85, 0x79, 0x00, 0x24, 0x82, 0xF8, 0x1A, 0x5C, 0xC5, 0x79, 0x82, 0xF8, 0x1B, 0x5C, 0x85, 0x7A, + 0x82, 0xF8, 0x1C, 0x5C, 0xC5, 0x7A, 0x82, 0xF8, 0x1D, 0x5C, 0x05, 0x7B, 0x82, 0xF8, 0x18, 0x5C, + 0x45, 0x7B, 0x82, 0xF8, 0x19, 0x5C, 0x23, 0x4A, 0x23, 0x46, 0x12, 0x68, 0x92, 0xF8, 0x21, 0x50, + 0xA5, 0x2D, 0x03, 0xD1, 0x12, 0xF9, 0x22, 0x4F, 0x92, 0xF9, 0x01, 0x30, 0x10, 0x30, 0xCD, 0xE9, + 0x01, 0x04, 0x1D, 0x48, 0x01, 0x22, 0x98, 0x30, 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x32, 0x08, 0x31, + 0x0F, 0xC9, 0xFF, 0xF7, 0xB7, 0xFC, 0x01, 0x20, 0x96, 0xE7, 0x2D, 0xE9, 0xFF, 0x41, 0x0F, 0x46, + 0x15, 0x46, 0x04, 0x46, 0x00, 0x26, 0x40, 0xF2, 0x7A, 0x31, 0x04, 0xF0, 0xB2, 0xFD, 0x0F, 0x48, + 0x01, 0x2D, 0x01, 0x78, 0x21, 0x71, 0x01, 0x79, 0x61, 0x71, 0x06, 0xD1, 0x0D, 0x49, 0x09, 0x68, + 0x8A, 0x7E, 0xA5, 0x2A, 0x01, 0xD1, 0x91, 0xF9, 0x1B, 0x60, 0x04, 0xF1, 0x10, 0x01, 0x08, 0x4B, + 0xCD, 0xE9, 0x00, 0x31, 0x00, 0x22, 0xCD, 0xE9, 0x02, 0x62, 0x00, 0xF1, 0x08, 0x01, 0x05, 0x46, + 0x0F, 0xC9, 0xFF, 0xF7, 0x3E, 0xFC, 0xA5, 0x20, 0x20, 0x70, 0x0B, 0xE0, 0x70, 0x07, 0x10, 0x00, + 0xFC, 0x4C, 0x01, 0x20, 0x24, 0x07, 0x10, 0x00, 0xEC, 0x57, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, + 0x24, 0x52, 0x01, 0x20, 0x10, 0x20, 0x60, 0x70, 0x67, 0x80, 0xD5, 0xE9, 0x00, 0x01, 0x48, 0x43, + 0x13, 0x30, 0x80, 0x08, 0x04, 0xB0, 0xB7, 0xE6, 0x2D, 0xE9, 0xFF, 0x41, 0x0F, 0x46, 0x15, 0x46, + 0x04, 0x46, 0x00, 0x26, 0x40, 0xF2, 0x7A, 0x31, 0x04, 0xF0, 0x73, 0xFD, 0x13, 0x48, 0x01, 0x2D, + 0x01, 0x78, 0x21, 0x71, 0x01, 0x79, 0x61, 0x71, 0x06, 0xD1, 0x11, 0x49, 0x09, 0x68, 0x0A, 0x7F, + 0xA5, 0x2A, 0x01, 0xD1, 0x91, 0xF9, 0x1D, 0x60, 0x04, 0xF1, 0x10, 0x01, 0x0D, 0x4A, 0xCD, 0xE9, + 0x00, 0x21, 0x00, 0x23, 0xCD, 0xE9, 0x02, 0x63, 0x00, 0xF1, 0x08, 0x01, 0x05, 0x46, 0x0F, 0xC9, + 0xFF, 0xF7, 0xFF, 0xFB, 0xA5, 0x20, 0x20, 0x70, 0x11, 0x20, 0x60, 0x70, 0x67, 0x80, 0xD5, 0xE9, + 0x00, 0x01, 0x48, 0x43, 0x13, 0x30, 0x80, 0x08, 0xCC, 0xE7, 0x00, 0x00, 0x70, 0x07, 0x10, 0x00, + 0x24, 0x07, 0x10, 0x00, 0x24, 0x52, 0x01, 0x20, 0x2D, 0xE9, 0xF0, 0x4F, 0x47, 0xF6, 0xFF, 0x77, + 0xDD, 0xE9, 0x09, 0xB5, 0x81, 0x46, 0xFE, 0x43, 0x01, 0x20, 0x9A, 0x46, 0x84, 0x46, 0x2C, 0x46, + 0x15, 0xE0, 0x00, 0xBF, 0x32, 0xF8, 0x14, 0x30, 0x31, 0xF8, 0x14, 0x80, 0xA3, 0xEB, 0x08, 0x03, + 0x1B, 0xB2, 0xBB, 0x42, 0x00, 0xDA, 0x1F, 0x46, 0xB3, 0x42, 0x00, 0xDD, 0x1E, 0x46, 0x00, 0x2B, + 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x0C, 0x02, 0xE0, 0x01, 0xDA, 0x4F, 0xF0, 0x00, 0x00, 0x64, 0x1E, + 0xE8, 0xD2, 0x20, 0xB1, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x00, 0x23, 0x09, 0xE0, 0x50, 0xEA, + 0x0C, 0x03, 0x06, 0xD0, 0x20, 0xB9, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x33, 0x46, 0x00, 0xE0, + 0x3B, 0x46, 0x00, 0x27, 0x3C, 0x46, 0x28, 0x46, 0xCB, 0xF1, 0x00, 0x0C, 0x0E, 0xE0, 0x00, 0xBF, + 0x32, 0xF8, 0x10, 0x60, 0x31, 0xF8, 0x10, 0x80, 0xA6, 0xEB, 0x08, 0x06, 0xF6, 0x1A, 0x36, 0xB2, + 0x56, 0x45, 0x03, 0xDA, 0x66, 0x45, 0x01, 0xDD, 0x37, 0x44, 0x64, 0x1C, 0x40, 0x1E, 0xEF, 0xD2, + 0x04, 0xB9, 0x01, 0x24, 0x97, 0xFB, 0xF4, 0xF0, 0x18, 0x44, 0x04, 0xE0, 0x31, 0xF8, 0x15, 0x20, + 0x02, 0x44, 0x29, 0xF8, 0x15, 0x20, 0x6D, 0x1E, 0xF8, 0xD2, 0xBD, 0xE8, 0xF0, 0x8F, 0xF0, 0xB5, + 0x00, 0x23, 0x06, 0x46, 0x1D, 0x46, 0x18, 0x46, 0x0E, 0xE0, 0x00, 0xBF, 0x36, 0xF9, 0x11, 0x40, + 0x00, 0x2C, 0x01, 0xDB, 0x27, 0x46, 0x00, 0xE0, 0x67, 0x42, 0x97, 0x42, 0x04, 0xDD, 0x00, 0x2C, + 0x01, 0xDD, 0x25, 0x44, 0x00, 0xE0, 0x23, 0x44, 0x49, 0x1E, 0xEF, 0xD2, 0x00, 0x2B, 0x00, 0xDA, + 0x5B, 0x42, 0xAB, 0x42, 0x00, 0xDD, 0x01, 0x20, 0xF0, 0xBD, 0x30, 0xB5, 0x07, 0xE0, 0x00, 0xBF, + 0x32, 0xF8, 0x13, 0x40, 0x31, 0xF8, 0x13, 0x50, 0x64, 0x1B, 0x20, 0xF8, 0x13, 0x40, 0x5B, 0x1E, + 0xF6, 0xD2, 0x30, 0xBD, 0x70, 0xB5, 0x04, 0x9C, 0x09, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x14, 0x50, + 0x32, 0xF9, 0x14, 0x60, 0x75, 0x43, 0x95, 0xFB, 0xF3, 0xF5, 0x20, 0xF8, 0x14, 0x50, 0x64, 0x1E, + 0xF4, 0xD2, 0x70, 0xBD, 0xF0, 0xB4, 0x04, 0x9C, 0x1C, 0xB9, 0x13, 0xB1, 0xC3, 0xF1, 0x10, 0x04, + 0x0E, 0xE0, 0xF0, 0xBC, 0x52, 0x00, 0x04, 0xF0, 0x25, 0xBC, 0x00, 0xBF, 0x30, 0xF9, 0x12, 0x50, + 0x31, 0xF9, 0x12, 0x60, 0x5D, 0x43, 0x06, 0xFB, 0x04, 0x55, 0x2D, 0x11, 0x20, 0xF8, 0x12, 0x50, + 0x52, 0x1E, 0xF3, 0xD2, 0xF0, 0xBC, 0x70, 0x47, 0xF0, 0xB4, 0x04, 0x9C, 0x1C, 0xB9, 0x13, 0xB1, + 0xC3, 0xF1, 0x80, 0x04, 0x0E, 0xE0, 0xF0, 0xBC, 0x52, 0x00, 0x04, 0xF0, 0x0B, 0xBC, 0x00, 0xBF, + 0x30, 0xF9, 0x12, 0x50, 0x31, 0xF9, 0x12, 0x60, 0x5D, 0x43, 0x06, 0xFB, 0x04, 0x55, 0xED, 0x11, + 0x20, 0xF8, 0x12, 0x50, 0x52, 0x1E, 0xF3, 0xD2, 0xE4, 0xE7, 0xF0, 0xB5, 0x00, 0x2B, 0x19, 0xD0, + 0x14, 0x46, 0x15, 0xE0, 0x00, 0x27, 0x3E, 0x46, 0xE5, 0x1A, 0x04, 0xEB, 0x03, 0x0C, 0x08, 0xE0, + 0x00, 0x2D, 0x05, 0xDB, 0x95, 0x42, 0x03, 0xDA, 0x31, 0xF9, 0x15, 0xE0, 0x76, 0x1C, 0x77, 0x44, + 0x6D, 0x1C, 0xAC, 0x45, 0xF4, 0xDA, 0x1E, 0xB1, 0x97, 0xFB, 0xF6, 0xF5, 0x20, 0xF8, 0x14, 0x50, + 0x64, 0x1E, 0xE7, 0xD2, 0xF0, 0xBD, 0x70, 0xB5, 0x0C, 0x46, 0x15, 0x46, 0xA0, 0x42, 0x04, 0xD0, + 0x01, 0x46, 0x6A, 0x00, 0x20, 0x46, 0x04, 0xF0, 0xD5, 0xFB, 0x00, 0x20, 0x17, 0xE0, 0x01, 0x46, + 0x42, 0x1C, 0x07, 0xE0, 0x34, 0xF9, 0x12, 0x60, 0x34, 0xF9, 0x11, 0x30, 0x9E, 0x42, 0x00, 0xDA, + 0x11, 0x46, 0x52, 0x1C, 0xAA, 0x42, 0xF5, 0xD3, 0x88, 0x42, 0x07, 0xD0, 0x34, 0xF8, 0x10, 0x20, + 0x34, 0xF8, 0x11, 0x30, 0x24, 0xF8, 0x10, 0x30, 0x24, 0xF8, 0x11, 0x20, 0x40, 0x1C, 0xB0, 0xEB, + 0x55, 0x0F, 0xE4, 0xD9, 0xE9, 0x07, 0x25, 0xF0, 0x01, 0x00, 0x01, 0xD0, 0x20, 0x5E, 0x70, 0xBD, + 0x21, 0x5E, 0x20, 0x44, 0x30, 0xF9, 0x02, 0x0C, 0x08, 0x44, 0x40, 0x10, 0x70, 0xBD, 0x03, 0x46, + 0x00, 0x20, 0x04, 0xE0, 0x33, 0xF9, 0x11, 0x20, 0x82, 0x42, 0x00, 0xDD, 0x10, 0x46, 0x49, 0x1E, + 0xF8, 0xD2, 0x70, 0x47, 0x03, 0x46, 0x47, 0xF6, 0xFF, 0x70, 0x04, 0xE0, 0x33, 0xF9, 0x11, 0x20, + 0x82, 0x42, 0x00, 0xDA, 0x10, 0x46, 0x49, 0x1E, 0xF8, 0xD2, 0x00, 0x28, 0x00, 0xDA, 0x00, 0x20, + 0x70, 0x47, 0x02, 0x46, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xE0, 0x00, 0xBF, 0x32, 0xF9, 0x11, 0x30, + 0x83, 0x42, 0x00, 0xDD, 0x18, 0x46, 0x49, 0x1E, 0xF8, 0xD2, 0x70, 0x47, 0x70, 0xB5, 0x05, 0x00, + 0x03, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0xF0, 0xBE, 0xBE, 0xFE, 0x4C, 0x21, 0x46, 0x60, 0x78, + 0x09, 0x79, 0x30, 0xB1, 0x0A, 0x46, 0xFC, 0x49, 0x01, 0xF1, 0x98, 0x00, 0x01, 0xF0, 0x00, 0xFF, + 0x0B, 0xE0, 0x20, 0x78, 0x01, 0xF0, 0xCA, 0xFF, 0x21, 0x79, 0x4A, 0x00, 0xF6, 0x49, 0x01, 0xEB, + 0x40, 0x01, 0xF5, 0x48, 0x98, 0x30, 0x04, 0xF0, 0x65, 0xFB, 0xA0, 0x78, 0xF3, 0x4E, 0x28, 0xB1, + 0xF1, 0x48, 0x21, 0x79, 0x98, 0x30, 0x01, 0xF0, 0xB7, 0xFF, 0x01, 0xE0, 0xEE, 0x48, 0x98, 0x30, + 0xB0, 0x62, 0xE0, 0x78, 0x86, 0xF8, 0x31, 0x00, 0x28, 0x46, 0xD2, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, + 0xDF, 0xF8, 0xAC, 0xA3, 0x83, 0x46, 0x01, 0x27, 0xDA, 0xF8, 0x00, 0x00, 0xB8, 0x46, 0x00, 0xF2, + 0x5E, 0x64, 0x90, 0xF8, 0xA6, 0x19, 0x90, 0xF8, 0xA2, 0x59, 0x01, 0xF0, 0x1F, 0x06, 0x90, 0xF8, + 0xA3, 0x19, 0x01, 0xF0, 0x0F, 0x09, 0x90, 0xF8, 0x82, 0x19, 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, + 0x58, 0x16, 0x90, 0xF8, 0x59, 0x06, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xFC, 0xFE, + 0x07, 0x46, 0xDA, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x82, 0x19, 0x49, 0x06, 0x09, 0xD5, 0x90, 0xF8, + 0x68, 0x18, 0x90, 0xF8, 0x69, 0x08, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xEC, 0xFE, + 0x80, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x85, 0x42, 0x00, 0xD9, 0x05, 0x46, 0x1F, 0x2E, 0x00, 0xD9, + 0x1F, 0x26, 0x76, 0x1C, 0x75, 0x43, 0x09, 0xF1, 0x01, 0x00, 0x45, 0x43, 0xC5, 0xEB, 0x45, 0x20, + 0x78, 0x43, 0xDA, 0xF8, 0x00, 0x20, 0x00, 0xFB, 0x08, 0xF0, 0xC0, 0x13, 0x92, 0xF8, 0x50, 0x1A, + 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x20, 0x00, 0x89, 0x06, 0x11, 0xD5, 0x00, 0x21, 0xBB, 0xF1, + 0x01, 0x0F, 0x06, 0xD1, 0x92, 0xF8, 0x56, 0x1A, 0x0A, 0x07, 0x01, 0xF0, 0x07, 0x01, 0x00, 0xD5, + 0x49, 0x42, 0x40, 0x18, 0x01, 0xD5, 0x00, 0x20, 0x02, 0xE0, 0x1F, 0x28, 0x00, 0xDD, 0x1F, 0x20, + 0xC0, 0xB2, 0xBD, 0xE8, 0xF0, 0x9F, 0xF8, 0xB5, 0x04, 0x46, 0x02, 0xF0, 0xD7, 0xFB, 0xB6, 0x48, + 0x02, 0xF0, 0xD9, 0xFB, 0xA4, 0xF8, 0x76, 0x00, 0x01, 0xF0, 0x98, 0xFE, 0xB1, 0x4A, 0x0B, 0x46, + 0x12, 0x78, 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x02, 0xF0, 0x97, 0xFE, 0x01, 0xF0, 0x93, 0xFE, + 0x02, 0x46, 0x0B, 0x46, 0x20, 0x46, 0x02, 0xF0, 0xC6, 0xFE, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xFF, + 0xAB, 0x4D, 0xB4, 0xF8, 0x56, 0x10, 0x28, 0x68, 0xB0, 0xF8, 0xC0, 0x20, 0x62, 0xF3, 0x09, 0x01, + 0xA4, 0xF8, 0x56, 0x10, 0x90, 0xF8, 0xBF, 0x00, 0x94, 0xF8, 0x55, 0x10, 0x60, 0xF3, 0x03, 0x01, + 0x84, 0xF8, 0x55, 0x10, 0x05, 0x21, 0x20, 0x46, 0x02, 0xF0, 0xD6, 0xFB, 0x28, 0x68, 0x90, 0xF8, + 0xA2, 0x09, 0xA0, 0x70, 0x28, 0x68, 0x21, 0x8E, 0xB0, 0xF8, 0xA7, 0x29, 0x62, 0xF3, 0x08, 0x01, + 0x21, 0x86, 0x90, 0xF8, 0xA3, 0x09, 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x02, 0xF0, 0x3B, 0xFC, + 0x28, 0x68, 0x34, 0xF8, 0x1A, 0x1F, 0xB0, 0xF8, 0x8E, 0x29, 0x62, 0xF3, 0x0B, 0x01, 0x24, 0xF8, + 0x14, 0x19, 0xB0, 0xF8, 0x8C, 0x29, 0x61, 0x89, 0x62, 0xF3, 0x0B, 0x01, 0x61, 0x81, 0xB0, 0xF8, + 0x8A, 0x19, 0xE0, 0x88, 0x61, 0xF3, 0x0B, 0x00, 0xE0, 0x80, 0x14, 0xF8, 0x05, 0x0C, 0x20, 0xF0, + 0x0C, 0x00, 0x04, 0xF8, 0x05, 0x0C, 0x29, 0x68, 0x20, 0x7B, 0x91, 0xF8, 0xA4, 0x29, 0x62, 0xF3, + 0x01, 0x00, 0x20, 0x73, 0x91, 0xF8, 0xA4, 0x29, 0x92, 0x08, 0x62, 0xF3, 0x87, 0x10, 0x20, 0x73, + 0x91, 0xF8, 0x82, 0x09, 0x62, 0x78, 0x60, 0xF3, 0x00, 0x02, 0x62, 0x70, 0x91, 0xF8, 0x85, 0x09, + 0xE0, 0x70, 0x80, 0x48, 0x90, 0xF8, 0x18, 0x1C, 0x21, 0x76, 0x90, 0xF8, 0x19, 0x1C, 0xA1, 0x77, + 0x90, 0xF8, 0x1A, 0x1C, 0x61, 0x76, 0x90, 0xF8, 0x1B, 0x1C, 0xE1, 0x77, 0x90, 0xF8, 0x1C, 0x1C, + 0xA1, 0x76, 0x90, 0xF8, 0x1D, 0x0C, 0x84, 0xF8, 0x20, 0x00, 0x77, 0x48, 0x02, 0xF0, 0x53, 0xFB, + 0xA4, 0xF8, 0x7A, 0x00, 0x74, 0x48, 0x20, 0x30, 0x02, 0xF0, 0x4D, 0xFB, 0xA4, 0xF8, 0x7E, 0x00, + 0x28, 0x68, 0x90, 0xF8, 0x92, 0x19, 0x0A, 0x09, 0x14, 0xF8, 0x16, 0x1F, 0x62, 0xF3, 0x07, 0x11, + 0x04, 0xF8, 0x06, 0x1B, 0x90, 0xF8, 0x97, 0x29, 0x13, 0x09, 0x22, 0x78, 0x63, 0xF3, 0x07, 0x12, + 0x22, 0x70, 0x90, 0xF8, 0x93, 0x69, 0x14, 0xF8, 0x05, 0x3C, 0x66, 0xF3, 0x03, 0x03, 0x04, 0xF8, + 0x05, 0x3C, 0x90, 0xF8, 0x98, 0x79, 0x66, 0x78, 0x67, 0xF3, 0x03, 0x06, 0x66, 0x70, 0x90, 0xF8, + 0x93, 0x79, 0x3F, 0x09, 0x67, 0xF3, 0x07, 0x13, 0x04, 0xF8, 0x05, 0x3C, 0x90, 0xF8, 0x98, 0x39, + 0x1B, 0x09, 0x63, 0xF3, 0x07, 0x16, 0x66, 0x70, 0x90, 0xF8, 0x92, 0x39, 0x63, 0xF3, 0x00, 0x01, + 0x04, 0xF8, 0x06, 0x1C, 0x90, 0xF8, 0x97, 0x19, 0x61, 0xF3, 0x00, 0x02, 0x04, 0xF8, 0x22, 0x29, + 0x90, 0xF8, 0x87, 0x09, 0x01, 0x09, 0x20, 0x46, 0x02, 0xF0, 0xB9, 0xFB, 0x52, 0x48, 0x48, 0x38, + 0x02, 0xF0, 0x09, 0xFB, 0xA4, 0xF8, 0x7E, 0x00, 0x4F, 0x48, 0x27, 0x34, 0x28, 0x38, 0x02, 0xF0, + 0x02, 0xFB, 0xA4, 0xF8, 0x5B, 0x00, 0x29, 0x68, 0x91, 0xF8, 0x84, 0x09, 0xC2, 0x08, 0x20, 0x78, + 0x62, 0xF3, 0x83, 0x00, 0x20, 0x70, 0x91, 0xF8, 0x84, 0x29, 0x52, 0x08, 0x62, 0xF3, 0x00, 0x00, + 0x20, 0x70, 0x91, 0xF8, 0x84, 0x29, 0x92, 0x08, 0x62, 0xF3, 0x41, 0x00, 0x04, 0xF8, 0x27, 0x09, + 0x91, 0xF8, 0x83, 0x09, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x02, 0xF0, 0x71, 0xFB, 0x28, 0x68, + 0x90, 0xF8, 0x83, 0x09, 0x01, 0x09, 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, 0x04, 0x10, 0x20, 0x70, + 0x3A, 0x48, 0x02, 0xF0, 0xD8, 0xFA, 0xA4, 0xF8, 0x60, 0x00, 0x38, 0x48, 0x20, 0x30, 0x02, 0xF0, + 0xD2, 0xFA, 0xA4, 0xF8, 0x62, 0x00, 0x28, 0x68, 0x90, 0xF8, 0x82, 0x19, 0xCA, 0x08, 0xE1, 0x7A, + 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, 0x90, 0xF8, 0x83, 0x09, 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, + 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x18, 0xFE, 0x28, 0x68, 0x90, 0xF8, + 0x86, 0x09, 0x81, 0x09, 0x20, 0x46, 0x02, 0xF0, 0x30, 0xFB, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, + 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, 0xF0, 0x00, 0xA0, 0x30, 0x04, 0xF8, 0x1C, 0x09, 0x29, 0x68, + 0x91, 0xF8, 0x82, 0x09, 0x82, 0x09, 0x60, 0x7F, 0x62, 0xF3, 0x00, 0x00, 0x60, 0x77, 0x91, 0xF8, + 0x82, 0x29, 0x52, 0x09, 0x62, 0xF3, 0x41, 0x00, 0x60, 0x77, 0x91, 0xF8, 0x88, 0x29, 0x62, 0xF3, + 0x82, 0x00, 0x60, 0x77, 0x91, 0xF8, 0xA5, 0x09, 0xE2, 0x7D, 0x60, 0xF3, 0x04, 0x02, 0xE2, 0x75, + 0x91, 0xF8, 0xA6, 0x09, 0xA1, 0x7D, 0x60, 0xF3, 0x04, 0x01, 0x0F, 0x48, 0xA1, 0x75, 0x08, 0x38, + 0x94, 0xF8, 0x49, 0x10, 0x40, 0x78, 0x60, 0xF3, 0x04, 0x01, 0x0F, 0x48, 0x84, 0xF8, 0x49, 0x10, + 0xE8, 0x30, 0x02, 0xF0, 0x80, 0xFA, 0xA4, 0xF8, 0x64, 0x00, 0x28, 0x68, 0x21, 0x8B, 0xB0, 0xF8, + 0x90, 0x29, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x83, 0x90, 0xF8, 0x86, 0x19, 0xCA, 0x08, 0x94, 0xF8, + 0x22, 0x10, 0x0D, 0xE0, 0x88, 0x07, 0x10, 0x00, 0x00, 0x5D, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xFC, 0x4C, 0x01, 0x20, 0xCC, 0x58, 0x01, 0x20, 0xB0, 0x5C, 0x01, 0x20, + 0x62, 0xF3, 0x02, 0x01, 0x84, 0xF8, 0x22, 0x10, 0x10, 0xF8, 0xE3, 0x2F, 0x21, 0x7D, 0x62, 0xF3, + 0x03, 0x01, 0x21, 0x75, 0x10, 0xF8, 0xE3, 0x1B, 0x0A, 0x09, 0x61, 0x7D, 0x62, 0xF3, 0x03, 0x01, + 0x61, 0x75, 0x90, 0xF8, 0xC1, 0x17, 0xE2, 0x7C, 0x61, 0xF3, 0x02, 0x02, 0xE2, 0x74, 0x90, 0xF8, + 0xBC, 0x17, 0xCA, 0x09, 0xA1, 0x7F, 0x62, 0xF3, 0x00, 0x01, 0xA1, 0x77, 0x94, 0xF8, 0x49, 0x10, + 0x41, 0xF0, 0x20, 0x01, 0x84, 0xF8, 0x49, 0x10, 0x90, 0xF8, 0xBE, 0x27, 0xD2, 0x09, 0x62, 0xF3, + 0xC7, 0x11, 0x84, 0xF8, 0x49, 0x10, 0xB0, 0xF8, 0xD6, 0x27, 0xB4, 0xF8, 0x4A, 0x10, 0x62, 0xF3, + 0x08, 0x01, 0xA4, 0xF8, 0x4A, 0x10, 0x00, 0x21, 0xE1, 0x64, 0x90, 0xF8, 0xC1, 0x17, 0xCA, 0x08, + 0x61, 0x7F, 0x62, 0xF3, 0xC3, 0x01, 0x61, 0x77, 0x90, 0xF8, 0xBC, 0x27, 0x12, 0x09, 0x62, 0xF3, + 0x04, 0x11, 0x61, 0x77, 0x90, 0xF8, 0xDF, 0x17, 0x4A, 0x09, 0x14, 0xF8, 0x0E, 0x1C, 0x62, 0xF3, + 0x06, 0x11, 0x04, 0xF8, 0x0E, 0x1C, 0x90, 0xF8, 0xBD, 0x17, 0x4A, 0x09, 0xA1, 0x78, 0x62, 0xF3, + 0xC3, 0x01, 0xA1, 0x70, 0x90, 0xF8, 0xBC, 0x27, 0x52, 0x08, 0x62, 0xF3, 0x04, 0x11, 0xA1, 0x70, + 0x90, 0xF8, 0xBE, 0x07, 0x80, 0x09, 0x60, 0xF3, 0x86, 0x11, 0xA1, 0x70, 0xF8, 0xBD, 0x2D, 0xE9, + 0xF0, 0x41, 0x04, 0x46, 0x54, 0x4D, 0x01, 0x20, 0x01, 0x29, 0xA8, 0x70, 0x08, 0xD0, 0x00, 0x26, + 0x52, 0x4F, 0x02, 0x29, 0x08, 0xD0, 0x03, 0x29, 0x14, 0xD0, 0x04, 0x29, 0x2C, 0xD1, 0x3D, 0xE0, + 0x20, 0x46, 0x00, 0xF0, 0x94, 0xF8, 0x27, 0xE0, 0x4D, 0x48, 0xFF, 0xF7, 0x0C, 0xFE, 0x20, 0x46, + 0x00, 0xF0, 0x8D, 0xF8, 0xB8, 0x78, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, + 0x5F, 0x10, 0x14, 0xE0, 0x46, 0x48, 0xFF, 0xF7, 0xFE, 0xFD, 0x20, 0x46, 0x00, 0xF0, 0x7F, 0xF8, + 0xF8, 0x78, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0x94, 0xF8, + 0x27, 0x00, 0x20, 0xF0, 0x02, 0x00, 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x00, 0x21, + 0x20, 0x46, 0x02, 0xF0, 0x68, 0xFA, 0xAE, 0x70, 0x20, 0x46, 0x01, 0xF0, 0x83, 0xFE, 0x94, 0xF8, + 0x27, 0x00, 0x40, 0xF3, 0x00, 0x00, 0x40, 0x1C, 0xE8, 0x70, 0x36, 0x48, 0x00, 0x68, 0x90, 0xF8, + 0x83, 0x09, 0xC0, 0xF3, 0x80, 0x10, 0x68, 0x70, 0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x46, 0x00, 0xF0, + 0x56, 0xF8, 0x20, 0x46, 0x01, 0xF0, 0x67, 0xFD, 0xE5, 0xE7, 0x7C, 0xB5, 0x01, 0xF0, 0x6E, 0xFC, + 0xCD, 0xE9, 0x00, 0x01, 0x08, 0x21, 0x68, 0x46, 0x02, 0xF0, 0xF4, 0xFD, 0x26, 0x49, 0x27, 0x4D, + 0x08, 0x71, 0x00, 0x20, 0x28, 0x60, 0x28, 0x71, 0x01, 0x24, 0xE0, 0xB2, 0xFF, 0xF7, 0x56, 0xFD, + 0x28, 0x55, 0x64, 0x1C, 0x05, 0x2C, 0xF8, 0xDB, 0x21, 0x48, 0xFF, 0xF7, 0xB4, 0xFD, 0x7C, 0xBD, + 0x30, 0xB5, 0x01, 0x7A, 0xA9, 0xB0, 0x79, 0xB3, 0x68, 0x46, 0xFF, 0xF7, 0x88, 0xFF, 0x9D, 0xF8, + 0x12, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0xB1, 0xFC, 0x1A, 0x4C, 0x20, 0x68, 0x00, 0xF2, + 0x5E, 0x63, 0x00, 0xF6, 0x6E, 0x05, 0x90, 0xF8, 0x58, 0x16, 0x90, 0xF8, 0x59, 0x06, 0x03, 0xEB, + 0x40, 0x00, 0x01, 0xF0, 0x74, 0xFC, 0x20, 0x68, 0x90, 0xF8, 0x68, 0x18, 0x90, 0xF8, 0x69, 0x08, + 0x05, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0x82, 0xFC, 0x0B, 0x48, 0x41, 0x78, 0x01, 0xB1, 0x02, 0x21, + 0x01, 0x70, 0xC9, 0xB2, 0x68, 0x46, 0x02, 0xF0, 0x80, 0xFC, 0x0B, 0x49, 0x68, 0x46, 0x02, 0xF0, + 0xB1, 0xFC, 0x00, 0x20, 0x29, 0xB0, 0x30, 0xBD, 0xFF, 0xE7, 0x01, 0x20, 0xFA, 0xE7, 0xA4, 0x22, + 0x03, 0x49, 0x04, 0xF0, 0x67, 0xB8, 0x00, 0x00, 0x88, 0x07, 0x10, 0x00, 0xF8, 0x5C, 0x01, 0x20, + 0x48, 0x7F, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xBD, 0x20, 0x01, 0x00, 0x10, 0xB5, 0x04, 0x00, + 0x03, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x96, 0xBB, 0x26, 0x48, 0x26, 0x49, 0x00, 0x78, + 0x42, 0x00, 0x01, 0xEB, 0x40, 0x01, 0x24, 0x48, 0x98, 0x30, 0x04, 0xF0, 0x4B, 0xF8, 0x22, 0x48, + 0x22, 0x49, 0x98, 0x30, 0x48, 0x62, 0x20, 0x46, 0xEB, 0xE7, 0x1C, 0xB5, 0x01, 0xF0, 0xF6, 0xFB, + 0xCD, 0xE9, 0x00, 0x01, 0x08, 0x21, 0x68, 0x46, 0x02, 0xF0, 0x7C, 0xFD, 0x19, 0x49, 0x1C, 0x4C, + 0x08, 0x70, 0x20, 0x46, 0x00, 0xF0, 0x39, 0xFB, 0x17, 0x48, 0x02, 0xF0, 0x24, 0xF9, 0xA4, 0xF8, + 0x76, 0x00, 0x18, 0x48, 0x01, 0x68, 0xA0, 0x7C, 0x91, 0xF8, 0x50, 0x21, 0x62, 0xF3, 0x01, 0x00, + 0xA0, 0x74, 0x91, 0xF8, 0x50, 0x11, 0x89, 0x08, 0x61, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0x1C, 0xBD, + 0x10, 0xB5, 0x0F, 0x4C, 0xC0, 0x79, 0x98, 0xB1, 0x20, 0x46, 0x01, 0xF0, 0xCB, 0xFD, 0xA0, 0x7C, + 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0x32, 0xFC, 0x00, 0xF0, 0x7B, 0xFB, 0x04, 0x21, 0x20, 0x46, + 0x02, 0xF0, 0x1B, 0xFC, 0x08, 0x49, 0x20, 0x46, 0x02, 0xF0, 0x4C, 0xFC, 0x00, 0x20, 0x10, 0xBD, + 0x01, 0x20, 0x10, 0xBD, 0x8D, 0x07, 0x10, 0x00, 0xE4, 0x5D, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00, + 0xEC, 0x7F, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x0D, 0x27, 0x01, 0x00, 0xFE, 0x49, 0xC8, 0x68, + 0x40, 0x1C, 0xC8, 0x60, 0x02, 0x28, 0x03, 0xD2, 0xFC, 0x49, 0x51, 0xF8, 0x20, 0x00, 0x00, 0x47, + 0x00, 0x20, 0x01, 0xF0, 0x30, 0xBB, 0x00, 0x28, 0x01, 0xD1, 0x02, 0xF0, 0x1C, 0xBC, 0x70, 0x47, + 0xF5, 0x49, 0x10, 0xB5, 0x0A, 0x79, 0x01, 0x20, 0x52, 0x1C, 0xD2, 0xB2, 0x0A, 0x71, 0x0B, 0x7A, + 0x9A, 0x42, 0x0A, 0xD8, 0x48, 0x7A, 0x48, 0xB1, 0x02, 0xF0, 0x5E, 0xFB, 0x03, 0x20, 0xED, 0xF7, + 0xCF, 0xFD, 0xEF, 0x48, 0x02, 0xF0, 0x4C, 0xFB, 0x00, 0x20, 0x10, 0xBD, 0x02, 0xF0, 0x03, 0xFC, + 0xFA, 0xE7, 0x70, 0xB5, 0x18, 0xB1, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0xF0, 0x0C, 0xBB, 0xE6, 0x4C, + 0x20, 0x7A, 0x08, 0xB1, 0xE7, 0x4D, 0x01, 0xE0, 0xE6, 0x4D, 0x76, 0x3D, 0xA0, 0x78, 0xE6, 0x49, + 0x82, 0x00, 0x01, 0xF5, 0xAE, 0x70, 0x04, 0xF0, 0x02, 0xF8, 0x60, 0x79, 0x28, 0xB1, 0xA2, 0x78, + 0xE1, 0x49, 0x28, 0x46, 0x01, 0xF0, 0x44, 0xFB, 0x0C, 0xE0, 0xA1, 0x78, 0x60, 0x78, 0x01, 0xF0, + 0x0D, 0xFC, 0xA1, 0x78, 0xC0, 0xB2, 0x4A, 0x00, 0xDB, 0x49, 0x01, 0xEB, 0x40, 0x01, 0x28, 0x46, + 0x03, 0xF0, 0xA8, 0xFF, 0xD7, 0x48, 0x23, 0x79, 0xA2, 0x78, 0x29, 0x46, 0x76, 0x38, 0x01, 0xF0, + 0x40, 0xFB, 0xFF, 0xF7, 0xB5, 0xFF, 0x00, 0x28, 0x15, 0xD0, 0xA0, 0x79, 0xD3, 0x4D, 0x01, 0x28, + 0x0B, 0xD0, 0xD0, 0x48, 0x76, 0x38, 0xA8, 0x61, 0xE0, 0x79, 0x85, 0xF8, 0x30, 0x00, 0x20, 0x79, + 0x85, 0xF8, 0x20, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x90, 0xE7, 0xCA, 0x48, 0xA1, 0x78, 0x76, 0x38, + 0x01, 0xF0, 0xE2, 0xFB, 0xEF, 0xE7, 0x70, 0xBD, 0x70, 0xB5, 0x18, 0xB1, 0xBD, 0xE8, 0x70, 0x40, + 0x01, 0xF0, 0xC1, 0xBA, 0xC0, 0x4C, 0x20, 0x7A, 0x08, 0xB1, 0xC2, 0x4D, 0x01, 0xE0, 0xC1, 0x4D, + 0x4C, 0x3D, 0xE0, 0x78, 0xC0, 0x49, 0x82, 0x00, 0x01, 0xF5, 0xD8, 0x70, 0x03, 0xF0, 0xB7, 0xFF, + 0x60, 0x79, 0x28, 0xB1, 0xE2, 0x78, 0xBC, 0x49, 0x28, 0x46, 0x01, 0xF0, 0xF9, 0xFA, 0x0C, 0xE0, + 0xE1, 0x78, 0x60, 0x78, 0x01, 0xF0, 0xC8, 0xFB, 0xE1, 0x78, 0xC0, 0xB2, 0x4A, 0x00, 0xB6, 0x49, + 0x01, 0xEB, 0x40, 0x01, 0x28, 0x46, 0x03, 0xF0, 0x5D, 0xFF, 0xB2, 0x48, 0x23, 0x79, 0xE2, 0x78, + 0x29, 0x46, 0x4C, 0x38, 0x01, 0xF0, 0xF5, 0xFA, 0xFF, 0xF7, 0x6A, 0xFF, 0x00, 0x28, 0x15, 0xD0, + 0xA0, 0x79, 0xAE, 0x4D, 0x01, 0x28, 0x0B, 0xD0, 0xAA, 0x48, 0x4C, 0x38, 0xE8, 0x61, 0xE0, 0x79, + 0x85, 0xF8, 0x30, 0x00, 0x20, 0x79, 0x85, 0xF8, 0x21, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x45, 0xE7, + 0xA4, 0x48, 0xE1, 0x78, 0x4C, 0x38, 0x01, 0xF0, 0x98, 0xFB, 0xEF, 0xE7, 0x70, 0xBD, 0x2D, 0xE9, + 0xF1, 0x4F, 0xDF, 0xF8, 0x8C, 0xB2, 0x01, 0x27, 0xB8, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0x00, 0xF2, + 0x5E, 0x64, 0x90, 0xF8, 0x55, 0x11, 0x90, 0xF8, 0x4E, 0x51, 0x01, 0xF0, 0x03, 0x0A, 0x90, 0xF8, + 0x52, 0x11, 0x01, 0xF0, 0x1F, 0x06, 0x90, 0xF8, 0x4F, 0x11, 0x01, 0xF0, 0x0F, 0x09, 0x90, 0xF8, + 0x32, 0x11, 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x56, 0x16, 0x90, 0xF8, 0x57, 0x06, 0x0A, 0x22, + 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xE0, 0xFA, 0x07, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8, + 0x32, 0x11, 0x49, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x66, 0x18, 0x90, 0xF8, 0x67, 0x08, 0x0A, 0x22, + 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xD0, 0xFA, 0x80, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x85, 0x42, + 0x00, 0xD9, 0x05, 0x46, 0x1F, 0x2E, 0x00, 0xD9, 0x1F, 0x26, 0x76, 0x1C, 0x75, 0x43, 0x09, 0xF1, + 0x01, 0x00, 0x45, 0x43, 0xC5, 0xEB, 0x45, 0x20, 0x78, 0x43, 0x00, 0xFB, 0x08, 0xF0, 0x0A, 0xF1, + 0x01, 0x01, 0x48, 0x43, 0xDB, 0xF8, 0x00, 0x20, 0xC0, 0x13, 0xB0, 0xFA, 0x80, 0xF0, 0x92, 0xF8, + 0x50, 0x1A, 0xC0, 0xF1, 0x20, 0x00, 0xC9, 0x06, 0x11, 0xD5, 0x00, 0x9B, 0x00, 0x21, 0x01, 0x2B, + 0x06, 0xD1, 0x92, 0xF8, 0x55, 0x1A, 0x0A, 0x07, 0x01, 0xF0, 0x07, 0x01, 0x00, 0xD5, 0x49, 0x42, + 0x40, 0x18, 0x01, 0xD5, 0x00, 0x20, 0x02, 0xE0, 0x1F, 0x28, 0x00, 0xDD, 0x1F, 0x20, 0xC0, 0xB2, + 0xBD, 0xE8, 0xF8, 0x8F, 0xF8, 0xB5, 0x04, 0x46, 0x01, 0xF0, 0xB8, 0xFF, 0x6A, 0x48, 0x01, 0xF0, + 0xBA, 0xFF, 0xA4, 0xF8, 0x76, 0x00, 0x01, 0xF0, 0x79, 0xFA, 0x63, 0x4D, 0x0B, 0x46, 0x6A, 0x78, + 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x02, 0xF0, 0x78, 0xFA, 0x01, 0xF0, 0x74, 0xFA, 0x02, 0x46, + 0x0B, 0x46, 0x20, 0x46, 0x02, 0xF0, 0xA7, 0xFA, 0x20, 0x46, 0x01, 0xF0, 0x1B, 0xFB, 0x60, 0x4E, + 0xB4, 0xF8, 0x56, 0x10, 0x30, 0x68, 0xB0, 0xF8, 0xC0, 0x20, 0x62, 0xF3, 0x09, 0x01, 0xA4, 0xF8, + 0x56, 0x10, 0x90, 0xF8, 0xBF, 0x00, 0x94, 0xF8, 0x55, 0x10, 0x60, 0xF3, 0x03, 0x01, 0x84, 0xF8, + 0x55, 0x10, 0x05, 0x21, 0x20, 0x46, 0x01, 0xF0, 0xB7, 0xFF, 0x30, 0x68, 0x90, 0xF8, 0x4E, 0x01, + 0xA0, 0x70, 0x30, 0x68, 0x21, 0x8E, 0xB0, 0xF8, 0x53, 0x21, 0x62, 0xF3, 0x08, 0x01, 0x21, 0x86, + 0x90, 0xF8, 0x4F, 0x01, 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x02, 0xF0, 0x1C, 0xF8, 0x30, 0x68, + 0x34, 0xF8, 0x1A, 0x1F, 0xB0, 0xF8, 0x3E, 0x21, 0x62, 0xF3, 0x0B, 0x01, 0x24, 0xF8, 0x12, 0x19, + 0xB0, 0xF8, 0x3C, 0x21, 0x21, 0x89, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x81, 0xB0, 0xF8, 0x3A, 0x21, + 0xA1, 0x88, 0x62, 0xF3, 0x0B, 0x01, 0xA1, 0x80, 0x90, 0xF8, 0x50, 0x21, 0xA1, 0x7A, 0x62, 0xF3, + 0x01, 0x01, 0xA1, 0x72, 0x90, 0xF8, 0x50, 0x21, 0x92, 0x08, 0x62, 0xF3, 0x87, 0x11, 0xA1, 0x72, + 0x90, 0xF8, 0x32, 0x11, 0x14, 0xF8, 0x01, 0x2C, 0x61, 0xF3, 0x00, 0x02, 0x04, 0xF8, 0x01, 0x2C, + 0x90, 0xF8, 0x35, 0x01, 0x60, 0x70, 0x37, 0x48, 0x90, 0xF8, 0x80, 0x1B, 0xA1, 0x75, 0x90, 0xF8, + 0x81, 0x1B, 0x21, 0x77, 0x90, 0xF8, 0x82, 0x1B, 0xE1, 0x75, 0x90, 0xF8, 0x83, 0x1B, 0x61, 0x77, + 0x90, 0xF8, 0x84, 0x1B, 0x21, 0x76, 0x90, 0xF8, 0x85, 0x0B, 0xA0, 0x77, 0x2E, 0x48, 0x01, 0xF0, + 0x3A, 0xFF, 0xA4, 0xF8, 0x78, 0x00, 0x2C, 0x48, 0x20, 0x30, 0x01, 0xF0, 0x34, 0xFF, 0xA4, 0xF8, + 0x7C, 0x00, 0x30, 0x68, 0x14, 0xF8, 0x14, 0x2F, 0x90, 0xF8, 0x42, 0x11, 0x09, 0x09, 0x61, 0xF3, + 0x07, 0x12, 0x04, 0xF8, 0x06, 0x2B, 0x90, 0xF8, 0x47, 0x11, 0x0B, 0x09, 0x21, 0x78, 0x63, 0xF3, + 0x07, 0x11, 0x21, 0x70, 0x90, 0xF8, 0x43, 0x31, 0x14, 0xF8, 0x05, 0x7C, 0x63, 0xF3, 0x03, 0x07, + 0x04, 0xF8, 0x05, 0x7C, 0x90, 0xF8, 0x48, 0xC1, 0x63, 0x78, 0x6C, 0xF3, 0x03, 0x03, 0x63, 0x70, + 0x90, 0xF8, 0x43, 0xC1, 0x4F, 0xEA, 0x1C, 0x1C, 0x6C, 0xF3, 0x07, 0x17, 0x04, 0xF8, 0x05, 0x7C, + 0x90, 0xF8, 0x48, 0x71, 0x3F, 0x09, 0x67, 0xF3, 0x07, 0x13, 0x63, 0x70, 0x90, 0xF8, 0x42, 0x31, + 0x63, 0xF3, 0x00, 0x02, 0x04, 0xF8, 0x06, 0x2C, 0x90, 0xF8, 0x47, 0x21, 0x62, 0xF3, 0x00, 0x01, + 0x04, 0xF8, 0x22, 0x19, 0x90, 0xF8, 0x37, 0x01, 0x01, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x9F, 0xFF, + 0x09, 0x48, 0x48, 0x38, 0x12, 0xE0, 0x00, 0x00, 0x90, 0x07, 0x10, 0x00, 0x44, 0x6F, 0x01, 0x00, + 0xE7, 0x27, 0x01, 0x00, 0xDE, 0x5F, 0x01, 0x20, 0xD0, 0x5E, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xFC, 0x4C, 0x01, 0x20, 0x34, 0x58, 0x01, 0x20, 0x01, 0xF0, 0xDB, 0xFE, + 0xA4, 0xF8, 0x7E, 0x00, 0xF7, 0x48, 0x27, 0x34, 0x01, 0xF0, 0xD5, 0xFE, 0xA4, 0xF8, 0x5B, 0x00, + 0x31, 0x68, 0x91, 0xF8, 0x34, 0x01, 0xC2, 0x08, 0x20, 0x78, 0x62, 0xF3, 0x83, 0x00, 0x20, 0x70, + 0x91, 0xF8, 0x34, 0x21, 0x52, 0x08, 0x62, 0xF3, 0x00, 0x00, 0x20, 0x70, 0x91, 0xF8, 0x34, 0x21, + 0x92, 0x08, 0x62, 0xF3, 0x41, 0x00, 0x04, 0xF8, 0x27, 0x09, 0x91, 0xF8, 0x33, 0x01, 0xC0, 0xF3, + 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, 0x44, 0xFF, 0x30, 0x68, 0x90, 0xF8, 0x33, 0x01, 0x01, 0x09, + 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, 0x04, 0x10, 0x20, 0x70, 0xE3, 0x48, 0x01, 0xF0, 0xAB, 0xFE, + 0xA4, 0xF8, 0x60, 0x00, 0xE0, 0x48, 0x20, 0x30, 0x01, 0xF0, 0xA5, 0xFE, 0xA4, 0xF8, 0x62, 0x00, + 0x30, 0x68, 0x90, 0xF8, 0x32, 0x11, 0xCA, 0x08, 0xE1, 0x7A, 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, + 0x90, 0xF8, 0x33, 0x01, 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, + 0x20, 0x46, 0x01, 0xF0, 0xD9, 0xF9, 0x30, 0x68, 0x90, 0xF8, 0x36, 0x01, 0x81, 0x09, 0x20, 0x46, + 0x01, 0xF0, 0x03, 0xFF, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, + 0xF0, 0x00, 0xA0, 0x30, 0x04, 0xF8, 0x1C, 0x09, 0x31, 0x68, 0x91, 0xF8, 0x32, 0x01, 0x82, 0x09, + 0x60, 0x7F, 0x62, 0xF3, 0x00, 0x00, 0x60, 0x77, 0x91, 0xF8, 0x32, 0x21, 0x52, 0x09, 0x62, 0xF3, + 0x41, 0x00, 0x60, 0x77, 0x91, 0xF8, 0x38, 0x21, 0x62, 0xF3, 0x82, 0x00, 0x60, 0x77, 0x91, 0xF8, + 0x51, 0x01, 0xE2, 0x7D, 0x60, 0xF3, 0x04, 0x02, 0xE2, 0x75, 0x91, 0xF8, 0x52, 0x01, 0xA1, 0x7D, + 0x60, 0xF3, 0x04, 0x01, 0xBD, 0x48, 0xA1, 0x75, 0x94, 0xF8, 0x49, 0x10, 0x40, 0x78, 0x60, 0xF3, + 0x04, 0x01, 0x84, 0xF8, 0x49, 0x10, 0xBA, 0x48, 0x01, 0xF0, 0x55, 0xFE, 0xA4, 0xF8, 0x64, 0x00, + 0x30, 0x68, 0x21, 0x8B, 0xB0, 0xF8, 0x40, 0x21, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x83, 0x90, 0xF8, + 0x36, 0x11, 0xCA, 0x08, 0x94, 0xF8, 0x22, 0x10, 0x62, 0xF3, 0x02, 0x01, 0x84, 0xF8, 0x22, 0x10, + 0x10, 0xF8, 0xE3, 0x1F, 0x22, 0x7D, 0x61, 0xF3, 0x03, 0x02, 0x22, 0x75, 0x10, 0xF8, 0x4F, 0x1B, + 0x0A, 0x09, 0x61, 0x7D, 0x62, 0xF3, 0x03, 0x01, 0x61, 0x75, 0x42, 0x79, 0xE1, 0x7C, 0x62, 0xF3, + 0x02, 0x01, 0xE1, 0x74, 0x01, 0x78, 0xCA, 0x09, 0xA1, 0x7F, 0x62, 0xF3, 0x00, 0x01, 0xA1, 0x77, + 0x94, 0xF8, 0x49, 0x10, 0x41, 0xF0, 0x20, 0x01, 0x84, 0xF8, 0x49, 0x10, 0x82, 0x78, 0xD2, 0x09, + 0x62, 0xF3, 0xC7, 0x11, 0x84, 0xF8, 0x49, 0x10, 0x42, 0x8B, 0xB4, 0xF8, 0x4A, 0x10, 0x62, 0xF3, + 0x08, 0x01, 0xA4, 0xF8, 0x4A, 0x10, 0x00, 0x21, 0xE1, 0x64, 0x41, 0x79, 0xCA, 0x08, 0x61, 0x7F, + 0x62, 0xF3, 0xC3, 0x01, 0x61, 0x77, 0x02, 0x78, 0x12, 0x09, 0x62, 0xF3, 0x04, 0x11, 0x61, 0x77, + 0xC1, 0x7F, 0x4A, 0x09, 0x14, 0xF8, 0x0E, 0x1C, 0x62, 0xF3, 0x06, 0x11, 0x04, 0xF8, 0x0E, 0x1C, + 0x41, 0x78, 0x4A, 0x09, 0xA1, 0x78, 0x62, 0xF3, 0xC3, 0x01, 0xA1, 0x70, 0x02, 0x78, 0x52, 0x08, + 0x62, 0xF3, 0x04, 0x11, 0xA1, 0x70, 0x82, 0x78, 0x92, 0x09, 0x62, 0xF3, 0x86, 0x11, 0xA1, 0x70, + 0x40, 0x78, 0xC0, 0xF3, 0x80, 0x10, 0x68, 0x71, 0xF8, 0xBD, 0xA4, 0x22, 0x85, 0x49, 0x03, 0xF0, + 0xF9, 0xBC, 0x2D, 0xE9, 0xF0, 0x41, 0x84, 0x4D, 0x00, 0x26, 0x01, 0x27, 0x2E, 0x71, 0xAF, 0x71, + 0x2E, 0x72, 0x0C, 0x46, 0x6E, 0x72, 0x01, 0x28, 0x07, 0xD0, 0x7C, 0x4F, 0x02, 0x28, 0x2C, 0xD0, + 0x03, 0x28, 0x14, 0xD0, 0x04, 0x28, 0x3A, 0xD1, 0x44, 0xE0, 0x08, 0x46, 0xFF, 0xF7, 0xE5, 0xFF, + 0x7A, 0x48, 0x01, 0x68, 0x91, 0xF8, 0x38, 0x01, 0x42, 0x06, 0x30, 0xD5, 0x91, 0xF8, 0x55, 0x11, + 0x00, 0x06, 0x01, 0xF0, 0x03, 0x01, 0x29, 0x72, 0x29, 0xD5, 0x6F, 0x72, 0x27, 0xE0, 0x71, 0x48, + 0xFF, 0xF7, 0x00, 0xFE, 0x20, 0x46, 0xFF, 0xF7, 0xD0, 0xFF, 0xF8, 0x78, 0x94, 0xF8, 0x5F, 0x10, + 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0x94, 0xF8, 0x27, 0x00, 0x20, 0xF0, 0x02, 0x00, + 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x0C, 0xE0, 0x66, 0x48, 0xFF, 0xF7, 0xEA, 0xFD, + 0x20, 0x46, 0xFF, 0xF7, 0xBA, 0xFF, 0xB8, 0x78, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, + 0x84, 0xF8, 0x5F, 0x10, 0x00, 0x21, 0x20, 0x46, 0x01, 0xF0, 0x3D, 0xFE, 0xAE, 0x71, 0x20, 0x46, + 0x01, 0xF0, 0x58, 0xFA, 0x94, 0xF8, 0x27, 0x00, 0x40, 0xF3, 0x00, 0x00, 0x40, 0x1C, 0xE8, 0x71, + 0xBD, 0xE8, 0xF0, 0x81, 0x08, 0x46, 0xFF, 0xF7, 0xA0, 0xFF, 0x20, 0x46, 0x01, 0xF0, 0x43, 0xF9, + 0xEC, 0xE7, 0x70, 0xB5, 0x55, 0x4D, 0x28, 0x68, 0x00, 0xF2, 0x5E, 0x62, 0x00, 0xF6, 0x6E, 0x04, + 0x90, 0xF8, 0x56, 0x16, 0x90, 0xF8, 0x57, 0x06, 0x02, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0x77, 0xF8, + 0x28, 0x68, 0x90, 0xF8, 0x66, 0x18, 0x90, 0xF8, 0x67, 0x08, 0x04, 0xEB, 0x40, 0x00, 0xBD, 0xE8, + 0x70, 0x40, 0x01, 0xF0, 0x83, 0xB8, 0x70, 0xB5, 0x47, 0x4D, 0x46, 0x4C, 0x68, 0x79, 0xA4, 0x34, + 0x00, 0xB1, 0x02, 0x20, 0x68, 0x70, 0x21, 0x46, 0x28, 0x78, 0xFF, 0xF7, 0x7A, 0xFF, 0x43, 0x48, + 0x01, 0x68, 0xA0, 0x7C, 0x91, 0xF8, 0x50, 0x21, 0x62, 0xF3, 0x01, 0x00, 0xA0, 0x74, 0x91, 0xF8, + 0x50, 0x11, 0x89, 0x08, 0x61, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0x69, 0x78, 0x20, 0x46, 0x02, 0xF0, + 0x6C, 0xF8, 0xA0, 0x7C, 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0x78, 0xF8, 0xFF, 0xF7, 0xC1, 0xFF, + 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x36, 0x49, 0x02, 0xF0, 0x94, 0xB8, 0x70, 0xB5, 0x32, 0x4D, + 0x30, 0x4C, 0x68, 0x79, 0xA4, 0x34, 0x08, 0xB1, 0x03, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x68, 0x70, + 0x21, 0x46, 0x28, 0x78, 0xFF, 0xF7, 0x4D, 0xFF, 0x2C, 0x48, 0x01, 0x68, 0x91, 0xF8, 0x50, 0x01, + 0x02, 0x09, 0xA0, 0x7C, 0x62, 0xF3, 0x01, 0x00, 0xA0, 0x74, 0x91, 0xF8, 0x50, 0x11, 0x89, 0x09, + 0x61, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0x69, 0x78, 0x20, 0x46, 0x02, 0xF0, 0x3E, 0xF8, 0xA0, 0x7C, + 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0x4A, 0xF8, 0xFF, 0xF7, 0x93, 0xFF, 0x20, 0x46, 0xBD, 0xE8, + 0x70, 0x40, 0x20, 0x49, 0x02, 0xF0, 0x66, 0xB8, 0x7F, 0xB5, 0x00, 0xF0, 0xD7, 0xFF, 0xCD, 0xE9, + 0x00, 0x01, 0x00, 0xF0, 0xD8, 0xFF, 0xCD, 0xE9, 0x02, 0x01, 0x08, 0x21, 0x68, 0x46, 0x02, 0xF0, + 0x59, 0xF9, 0x15, 0x4C, 0x08, 0x21, 0xA0, 0x70, 0x02, 0xA8, 0x02, 0xF0, 0x53, 0xF9, 0xE0, 0x70, + 0x0E, 0x4D, 0x01, 0x24, 0xE0, 0xB2, 0xFF, 0xF7, 0xD2, 0xFC, 0x28, 0x55, 0x64, 0x1C, 0x05, 0x2C, + 0xF8, 0xDB, 0x0C, 0x48, 0xFF, 0xF7, 0x36, 0xFD, 0x7F, 0xBD, 0x10, 0xB5, 0x80, 0x79, 0xD8, 0xB1, + 0x09, 0x49, 0x08, 0x70, 0x4F, 0xF0, 0xFF, 0x30, 0xC8, 0x60, 0xFF, 0xF7, 0xFF, 0xFB, 0x00, 0x20, + 0x10, 0xBD, 0x00, 0x00, 0x0C, 0x58, 0x01, 0x20, 0xB0, 0x5C, 0x01, 0x20, 0xC8, 0x5E, 0x01, 0x20, + 0xB4, 0x59, 0x01, 0x20, 0x90, 0x80, 0x10, 0x00, 0x90, 0x07, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, + 0x23, 0x28, 0x01, 0x00, 0xB9, 0x28, 0x01, 0x00, 0x01, 0x20, 0xE9, 0xE7, 0x10, 0xB9, 0x77, 0x4A, + 0x75, 0x49, 0x11, 0x61, 0x00, 0xF0, 0x1F, 0xBF, 0x70, 0xB5, 0x75, 0x4D, 0x04, 0x46, 0x28, 0x68, + 0x90, 0xF8, 0xF1, 0x01, 0xC0, 0xF3, 0x01, 0x12, 0xC0, 0xF3, 0x81, 0x01, 0x00, 0xF0, 0x03, 0x00, + 0xFE, 0xF7, 0xF9, 0xF8, 0x40, 0x1C, 0xC6, 0xB2, 0x20, 0x46, 0x00, 0xF0, 0xAA, 0xFC, 0x6A, 0x48, + 0x01, 0xF0, 0xB9, 0xFC, 0xA4, 0xF8, 0x76, 0x00, 0x00, 0x22, 0x31, 0x46, 0x20, 0x46, 0x01, 0xF0, + 0xB7, 0xFE, 0xA0, 0x79, 0x40, 0xF0, 0x02, 0x00, 0xA0, 0x71, 0x94, 0xF8, 0x6F, 0x00, 0x66, 0xF3, + 0x02, 0x00, 0x84, 0xF8, 0x6F, 0x00, 0x94, 0xF8, 0x6E, 0x00, 0x20, 0xF0, 0x0F, 0x00, 0x84, 0xF8, + 0x6E, 0x00, 0x29, 0x68, 0xA0, 0x7C, 0x91, 0xF8, 0x08, 0x21, 0x62, 0xF3, 0x01, 0x00, 0xA0, 0x74, + 0x91, 0xF8, 0x08, 0x21, 0x92, 0x08, 0x62, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0xA0, 0x89, 0x6F, 0xF3, + 0x0B, 0x00, 0xA0, 0x81, 0x91, 0xF8, 0x07, 0x01, 0xA0, 0x70, 0x94, 0xF8, 0x5E, 0x00, 0x00, 0x21, + 0x20, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, 0x20, 0x46, 0x01, 0xF0, 0x24, 0xFD, 0x28, 0x68, + 0x90, 0xF8, 0xF2, 0x11, 0x84, 0xF8, 0x66, 0x10, 0x90, 0xF8, 0xF3, 0x11, 0x84, 0xF8, 0x68, 0x10, + 0x90, 0xF8, 0xF4, 0x11, 0x84, 0xF8, 0x6A, 0x10, 0x90, 0xF8, 0xF5, 0x01, 0x84, 0xF8, 0x6C, 0x00, + 0x45, 0x48, 0x94, 0xF8, 0x5F, 0x10, 0x00, 0x1F, 0x40, 0x78, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, + 0x5F, 0x10, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, 0xA2, 0xBF, 0x10, 0xB5, 0x3E, 0x4C, + 0x00, 0x20, 0x24, 0x1F, 0x20, 0x80, 0x01, 0x20, 0x00, 0xF0, 0x3B, 0xF8, 0x60, 0x70, 0x3D, 0x48, + 0xFF, 0xF7, 0x8A, 0xFF, 0x3B, 0x48, 0x3C, 0x49, 0xB0, 0xF8, 0x4E, 0x00, 0x08, 0x80, 0x10, 0xBD, + 0x2D, 0xE9, 0xF0, 0x41, 0x37, 0x4E, 0x40, 0x79, 0x48, 0xB3, 0x37, 0x49, 0x30, 0x46, 0x09, 0x88, + 0xA6, 0xF8, 0x4E, 0x10, 0x01, 0xF0, 0x06, 0xF9, 0xB0, 0x7C, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF0, + 0x6D, 0xFF, 0x2F, 0x4F, 0x3C, 0x68, 0x04, 0xF2, 0x5E, 0x60, 0x94, 0xF8, 0x51, 0x26, 0x04, 0xF6, + 0x6E, 0x05, 0x94, 0xF8, 0x50, 0x16, 0x00, 0xEB, 0x42, 0x00, 0x00, 0xF0, 0x30, 0xFF, 0x38, 0x68, + 0x90, 0xF8, 0x60, 0x18, 0x90, 0xF8, 0x61, 0x08, 0x05, 0xEB, 0x40, 0x00, 0x00, 0xF0, 0x3E, 0xFF, + 0x26, 0x49, 0x30, 0x46, 0x01, 0xF0, 0x6C, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x01, 0x20, + 0xFB, 0xE7, 0x30, 0xB5, 0x1E, 0x49, 0x4F, 0xF4, 0x80, 0x75, 0x0A, 0x68, 0x92, 0xF8, 0x07, 0x11, + 0x92, 0xF8, 0xF5, 0x30, 0x92, 0xF8, 0xF2, 0x40, 0x03, 0xF0, 0x1F, 0x03, 0x04, 0xF0, 0x0F, 0x04, + 0xA9, 0x42, 0x00, 0xD9, 0x29, 0x46, 0x1F, 0x2B, 0x00, 0xD9, 0x1F, 0x23, 0x5B, 0x1C, 0x59, 0x43, + 0x49, 0x00, 0x64, 0x1C, 0x61, 0x43, 0xC1, 0xEB, 0x41, 0x21, 0xC9, 0x13, 0x92, 0xF8, 0x50, 0x3A, + 0xB1, 0xFA, 0x81, 0xF1, 0xC1, 0xF1, 0x20, 0x01, 0x9B, 0x07, 0x13, 0xD5, 0x00, 0x23, 0x01, 0x28, + 0x09, 0xD1, 0x92, 0xF8, 0x54, 0x0A, 0x02, 0x07, 0x03, 0xD5, 0x00, 0xF0, 0x07, 0x00, 0x43, 0x42, + 0x01, 0xE0, 0x00, 0xF0, 0x07, 0x03, 0xC9, 0x18, 0x01, 0xD5, 0x00, 0x21, 0x02, 0xE0, 0x1F, 0x29, + 0x00, 0xDD, 0x1F, 0x21, 0xC8, 0xB2, 0x30, 0xBD, 0x1C, 0x61, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0xD8, 0x81, 0x10, 0x00, 0xA0, 0x07, 0x10, 0x00, 0xFD, 0x2F, 0x01, 0x00, + 0x2D, 0xE9, 0xF0, 0x5F, 0xDF, 0xF8, 0xA4, 0x85, 0x83, 0x46, 0x4F, 0xF0, 0x01, 0x09, 0xD8, 0xF8, + 0x00, 0x00, 0x00, 0x27, 0xAB, 0xF1, 0x02, 0x01, 0x00, 0xF2, 0x5E, 0x64, 0xCA, 0x46, 0x06, 0x29, + 0x50, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x4F, 0x09, 0x2C, 0x4F, 0x2C, 0x03, 0x10, 0xF8, 0xD5, 0x6F, + 0x00, 0x79, 0x00, 0xF0, 0x1F, 0x05, 0x6D, 0xE0, 0x90, 0xF8, 0xF5, 0x10, 0x90, 0xF8, 0x01, 0x61, + 0x01, 0xF0, 0x1F, 0x05, 0x90, 0xF8, 0xF2, 0x10, 0x01, 0xF0, 0x0F, 0x07, 0x90, 0xF8, 0xE6, 0x10, + 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x52, 0x16, 0x90, 0xF8, 0x53, 0x06, 0x0A, 0x22, 0x04, 0xEB, + 0x40, 0x00, 0x00, 0xF0, 0x81, 0xFE, 0x81, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE6, 0x10, + 0x49, 0x06, 0x4F, 0xD5, 0x90, 0xF8, 0x62, 0x18, 0x90, 0xF8, 0x63, 0x08, 0x44, 0xE0, 0x90, 0xF8, + 0xFC, 0x10, 0x90, 0xF8, 0xF8, 0x60, 0x01, 0xF0, 0x1F, 0x05, 0x90, 0xF8, 0xF9, 0x10, 0x01, 0xF0, + 0x0F, 0x07, 0x90, 0xF8, 0xE6, 0x10, 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x54, 0x16, 0x90, 0xF8, + 0x55, 0x06, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x00, 0xF0, 0x5E, 0xFE, 0x81, 0x46, 0xD8, 0xF8, + 0x00, 0x00, 0x90, 0xF8, 0xE6, 0x10, 0x49, 0x06, 0x2C, 0xD5, 0x90, 0xF8, 0x64, 0x18, 0x90, 0xF8, + 0x65, 0x08, 0x21, 0xE0, 0x90, 0xF8, 0xF5, 0x10, 0x90, 0xF8, 0xF1, 0x60, 0x01, 0xF0, 0x1F, 0x05, + 0x90, 0xF8, 0xF2, 0x10, 0x01, 0xF0, 0x0F, 0x07, 0x90, 0xF8, 0xE6, 0x10, 0x89, 0x06, 0x09, 0xD5, + 0x90, 0xF8, 0x50, 0x16, 0x90, 0xF8, 0x51, 0x06, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x00, 0xF0, + 0x3B, 0xFE, 0x81, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE6, 0x10, 0x49, 0x06, 0x09, 0xD5, + 0x90, 0xF8, 0x60, 0x18, 0x90, 0xF8, 0x61, 0x08, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x00, 0xF0, + 0x2B, 0xFE, 0x82, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x86, 0x42, 0x00, 0xD9, 0x06, 0x46, 0x1F, 0x2D, + 0x00, 0xD9, 0x1F, 0x25, 0x6D, 0x1C, 0x6E, 0x43, 0x70, 0x00, 0x7F, 0x1C, 0x78, 0x43, 0xC0, 0xEB, + 0x40, 0x20, 0x00, 0xFB, 0x09, 0xF0, 0x00, 0xFB, 0x0A, 0xF0, 0xC0, 0x13, 0xD8, 0xF8, 0x00, 0x20, + 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x20, 0x01, 0x92, 0xF8, 0x50, 0x0A, 0xC0, 0x07, 0x23, 0xD0, + 0x00, 0x20, 0xBB, 0xF1, 0x05, 0x0F, 0x11, 0xD2, 0xDF, 0xE8, 0x0B, 0xF0, 0x10, 0x03, 0x06, 0x09, + 0x14, 0x00, 0x92, 0xF8, 0x51, 0x0A, 0x04, 0xE0, 0x92, 0xF8, 0x51, 0x0A, 0x0C, 0xE0, 0x92, 0xF8, + 0x52, 0x0A, 0x02, 0x07, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xD5, 0x40, 0x42, 0x09, 0x18, 0x08, 0xD5, + 0x00, 0x21, 0x09, 0xE0, 0x92, 0xF8, 0x52, 0x0A, 0x02, 0x06, 0xC0, 0xF3, 0x02, 0x10, 0xF4, 0xD4, + 0xF4, 0xE7, 0x1F, 0x29, 0x00, 0xDD, 0x1F, 0x21, 0xC8, 0xB2, 0xBD, 0xE8, 0xF0, 0x9F, 0x70, 0xB5, + 0x06, 0x00, 0x03, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, 0x55, 0xBD, 0x00, 0xF0, 0x18, 0xF8, + 0x01, 0x28, 0x14, 0xD1, 0xFE, 0x4D, 0xFF, 0x4C, 0x28, 0x78, 0x01, 0x28, 0x09, 0xD0, 0xFE, 0x48, + 0xA0, 0x60, 0x68, 0x78, 0xE0, 0x73, 0xE8, 0x78, 0xA0, 0x73, 0xE8, 0x88, 0xA0, 0x81, 0x30, 0x46, + 0xE8, 0xE7, 0x6A, 0x79, 0x29, 0x79, 0xF8, 0x48, 0x00, 0xF0, 0x55, 0xFE, 0xF0, 0xE7, 0x70, 0xBD, + 0xF3, 0x4B, 0x10, 0xB5, 0xD9, 0x78, 0xF5, 0x4C, 0x49, 0x1C, 0xCA, 0xB2, 0xDA, 0x70, 0x99, 0x78, + 0x01, 0x20, 0x8A, 0x42, 0x11, 0xD8, 0x19, 0x79, 0x58, 0x79, 0x41, 0x43, 0xEE, 0x48, 0xFD, 0xF7, + 0xB2, 0xFF, 0x01, 0xF0, 0xD8, 0xFA, 0xA4, 0xF8, 0x76, 0x00, 0x20, 0x46, 0x00, 0xF0, 0x92, 0xFF, + 0xEB, 0x49, 0x20, 0x46, 0x01, 0xF0, 0x14, 0xFD, 0x00, 0x20, 0x10, 0xBD, 0x38, 0xB5, 0x04, 0x46, + 0x01, 0xF0, 0xC4, 0xFA, 0xE4, 0x48, 0x01, 0xF0, 0xC6, 0xFA, 0xA4, 0xF8, 0x76, 0x00, 0x00, 0xF0, + 0x85, 0xFD, 0xDE, 0x4D, 0x0B, 0x46, 0x2A, 0x68, 0x92, 0xF8, 0xE7, 0x20, 0xC2, 0xF3, 0x41, 0x12, + 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x9A, 0xFC, 0x00, 0xF0, 0x7C, 0xFD, 0x02, 0x46, + 0x0B, 0x46, 0x20, 0x46, 0x01, 0xF0, 0xBF, 0xFC, 0xA0, 0x79, 0x20, 0xF0, 0x02, 0x00, 0xA0, 0x71, + 0x94, 0xF8, 0x6F, 0x00, 0x20, 0xF0, 0x07, 0x00, 0x84, 0xF8, 0x6F, 0x00, 0x94, 0xF8, 0x6E, 0x00, + 0x20, 0xF0, 0x0F, 0x00, 0x84, 0xF8, 0x6E, 0x00, 0x28, 0x68, 0x90, 0xF8, 0xE7, 0x00, 0xC0, 0xF3, + 0x41, 0x11, 0x20, 0x46, 0x01, 0xF0, 0xC1, 0xFC, 0x28, 0x68, 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, + 0x60, 0x0F, 0x94, 0xF8, 0x5E, 0x00, 0x7D, 0xD0, 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, + 0x20, 0x46, 0x00, 0xF0, 0xFF, 0xFD, 0x05, 0x21, 0x20, 0x46, 0x01, 0xF0, 0xAD, 0xFA, 0x28, 0x68, + 0x90, 0xF8, 0xF1, 0x00, 0xA0, 0x70, 0x28, 0x68, 0x21, 0x8E, 0xB0, 0xF8, 0xF6, 0x20, 0x62, 0xF3, + 0x08, 0x01, 0x21, 0x86, 0x90, 0xF8, 0xF2, 0x00, 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x01, 0xF0, + 0x12, 0xFB, 0x28, 0x68, 0x62, 0x7D, 0x90, 0xF8, 0xEA, 0x10, 0x61, 0xF3, 0x03, 0x02, 0x62, 0x75, + 0xB0, 0xF8, 0xED, 0x20, 0x21, 0x8A, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x82, 0x90, 0xF8, 0xF3, 0x10, + 0xA2, 0x7D, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x75, 0x10, 0xF8, 0xF2, 0x1F, 0x0A, 0x09, 0xA1, 0x7C, + 0x62, 0xF3, 0x01, 0x01, 0xA1, 0x74, 0x10, 0xF8, 0x0C, 0x29, 0x92, 0x09, 0x62, 0xF3, 0x87, 0x11, + 0xA1, 0x74, 0x01, 0x78, 0xE2, 0x79, 0x61, 0xF3, 0x00, 0x02, 0xE2, 0x71, 0xC1, 0x78, 0x61, 0x72, + 0x80, 0x79, 0x01, 0x09, 0x20, 0x46, 0x01, 0xF0, 0xF2, 0xFA, 0xA6, 0x48, 0x01, 0xF0, 0x43, 0xFA, + 0xA4, 0xF8, 0x7C, 0x00, 0x29, 0x68, 0x11, 0xF8, 0xE8, 0x0F, 0xC2, 0x08, 0x94, 0xF8, 0x27, 0x00, + 0x62, 0xF3, 0x83, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x11, 0xF8, 0x01, 0x29, 0x52, 0x08, 0x62, 0xF3, + 0x00, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x4A, 0x78, 0x92, 0x08, 0x62, 0xF3, 0x41, 0x00, 0x84, 0xF8, + 0x27, 0x00, 0x08, 0x78, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, 0xB1, 0xFA, 0x28, 0x68, + 0x90, 0xF8, 0xE7, 0x00, 0x01, 0x09, 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, 0x04, 0x10, 0x20, 0x70, + 0x91, 0x48, 0x01, 0xF0, 0x18, 0xFA, 0xA4, 0xF8, 0x5E, 0x00, 0x28, 0x68, 0x10, 0xF8, 0xE6, 0x1F, + 0xCA, 0x08, 0x00, 0xE0, 0x8F, 0xE0, 0xE1, 0x7A, 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, 0x40, 0x78, + 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, 0x20, 0x46, 0x00, 0xF0, + 0x3F, 0xFD, 0x28, 0x68, 0x90, 0xF8, 0xEC, 0x00, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, + 0x74, 0xFA, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, 0xF0, 0x00, + 0xA0, 0x30, 0x04, 0xF8, 0x0A, 0x09, 0x29, 0x68, 0x11, 0xF8, 0xE6, 0x0F, 0x82, 0x09, 0xE0, 0x7A, + 0x62, 0xF3, 0x00, 0x00, 0xE0, 0x72, 0x0A, 0x78, 0x52, 0x09, 0x62, 0xF3, 0x41, 0x00, 0xE0, 0x72, + 0x4A, 0x79, 0xD2, 0x09, 0x62, 0xF3, 0x82, 0x00, 0xE0, 0x72, 0x88, 0x7B, 0x62, 0x79, 0x60, 0xF3, + 0x04, 0x02, 0x62, 0x71, 0xC8, 0x7B, 0x21, 0x79, 0x60, 0xF3, 0x04, 0x01, 0x6F, 0x48, 0x21, 0x71, + 0x94, 0xF8, 0x37, 0x10, 0x40, 0x78, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x37, 0x10, 0x6C, 0x48, + 0x01, 0xF0, 0xC9, 0xF9, 0xA4, 0xF8, 0x52, 0x00, 0x28, 0x68, 0xE1, 0x88, 0xB0, 0xF8, 0xEF, 0x20, + 0x62, 0xF3, 0x0B, 0x01, 0xE1, 0x80, 0x90, 0xF8, 0xEB, 0x10, 0xCA, 0x08, 0x21, 0x7C, 0x62, 0xF3, + 0x02, 0x01, 0x21, 0x74, 0x10, 0xF8, 0xE2, 0x1F, 0xA2, 0x78, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x70, + 0x01, 0x78, 0x0A, 0x09, 0xE1, 0x78, 0x62, 0xF3, 0x03, 0x01, 0xE1, 0x70, 0x01, 0x7A, 0x0A, 0x09, + 0x61, 0x78, 0x62, 0xF3, 0x02, 0x01, 0x61, 0x70, 0x81, 0x79, 0x8A, 0x09, 0x21, 0x78, 0x62, 0xF3, + 0x00, 0x01, 0x21, 0x70, 0x01, 0x79, 0xCA, 0x09, 0x21, 0x7B, 0x62, 0xF3, 0x00, 0x01, 0x21, 0x73, + 0x94, 0xF8, 0x37, 0x10, 0x41, 0xF0, 0x20, 0x01, 0x84, 0xF8, 0x37, 0x10, 0x21, 0x8F, 0x6F, 0xF3, + 0x08, 0x01, 0x01, 0xF5, 0x80, 0x71, 0x21, 0x87, 0x00, 0x21, 0xC4, 0xF8, 0x3A, 0x10, 0x41, 0x7A, + 0x8A, 0x09, 0xE1, 0x7A, 0x62, 0xF3, 0xC3, 0x01, 0xE1, 0x72, 0x00, 0x79, 0x00, 0x09, 0x60, 0xF3, + 0x04, 0x11, 0xE1, 0x72, 0x38, 0xBD, 0x20, 0xF0, 0x01, 0x00, 0xEF, 0xE6, 0x38, 0xB5, 0x04, 0x46, + 0x01, 0xF0, 0x74, 0xF9, 0x3C, 0x48, 0x01, 0xF0, 0x76, 0xF9, 0xA4, 0xF8, 0x76, 0x00, 0x00, 0xF0, + 0x35, 0xFC, 0x36, 0x4D, 0x0B, 0x46, 0x2A, 0x68, 0x92, 0xF8, 0xC9, 0x20, 0xC2, 0xF3, 0x41, 0x12, + 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x4A, 0xFB, 0x00, 0xF0, 0x2C, 0xFC, 0x02, 0x46, + 0x0B, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x6F, 0xFB, 0xA0, 0x79, 0x20, 0xF0, 0x02, 0x00, 0xA0, 0x71, + 0x94, 0xF8, 0x6F, 0x00, 0x20, 0xF0, 0x07, 0x00, 0x84, 0xF8, 0x6F, 0x00, 0x94, 0xF8, 0x6E, 0x00, + 0x20, 0xF0, 0x0F, 0x00, 0x84, 0xF8, 0x6E, 0x00, 0x28, 0x68, 0x90, 0xF8, 0xC9, 0x00, 0xC0, 0xF3, + 0x41, 0x11, 0x20, 0x46, 0x01, 0xF0, 0x71, 0xFB, 0x28, 0x68, 0x90, 0xF8, 0xC9, 0x00, 0x10, 0xF0, + 0x60, 0x0F, 0x94, 0xF8, 0x5E, 0x00, 0x7D, 0xD0, 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, + 0x20, 0x46, 0x00, 0xF0, 0xAF, 0xFC, 0x28, 0x68, 0x90, 0xF8, 0xD5, 0x00, 0xA0, 0x70, 0x28, 0x68, + 0x21, 0x8E, 0xB0, 0xF8, 0xDA, 0x20, 0x62, 0xF3, 0x08, 0x01, 0x21, 0x86, 0x90, 0xF8, 0xD6, 0x00, + 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x01, 0xF0, 0xC6, 0xF9, 0x28, 0x68, 0x62, 0x7D, 0x90, 0xF8, + 0xCC, 0x10, 0x61, 0xF3, 0x03, 0x02, 0x62, 0x75, 0xB0, 0xF8, 0xCF, 0x20, 0x21, 0x8A, 0x62, 0xF3, + 0x0B, 0x01, 0x21, 0x82, 0x90, 0xF8, 0xD7, 0x10, 0xA2, 0x7D, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x75, + 0xB0, 0xF8, 0xD1, 0x20, 0xA1, 0x89, 0x62, 0xF3, 0x0B, 0x01, 0xA1, 0x81, 0x10, 0xF8, 0xD6, 0x1F, + 0x0A, 0x09, 0xA1, 0x7C, 0x62, 0xF3, 0x01, 0x01, 0xA1, 0x74, 0x13, 0xE0, 0x20, 0x07, 0x10, 0x00, + 0xA2, 0x07, 0x10, 0x00, 0xD4, 0x83, 0x10, 0x00, 0x4C, 0x62, 0x01, 0x20, 0x20, 0x83, 0x10, 0x00, + 0x8F, 0x33, 0x01, 0x00, 0xFC, 0x4C, 0x01, 0x20, 0x88, 0x5C, 0x01, 0x20, 0x4E, 0x7B, 0x01, 0x20, + 0xB4, 0x59, 0x01, 0x20, 0x10, 0xF8, 0x0D, 0x29, 0x92, 0x09, 0x62, 0xF3, 0x87, 0x11, 0xA1, 0x74, + 0x10, 0xF8, 0x01, 0x1C, 0xE2, 0x79, 0x61, 0xF3, 0x00, 0x02, 0xE2, 0x71, 0x81, 0x78, 0x61, 0x72, + 0x40, 0x79, 0x01, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x8A, 0xF9, 0xFB, 0x48, 0x01, 0xF0, 0xDB, 0xF8, + 0xA4, 0xF8, 0x7C, 0x00, 0x28, 0x68, 0x10, 0xF8, 0xCA, 0x1F, 0xCA, 0x08, 0x94, 0xF8, 0x27, 0x10, + 0x62, 0xF3, 0x83, 0x01, 0x84, 0xF8, 0x27, 0x10, 0x10, 0xF8, 0x01, 0x29, 0x52, 0x08, 0x62, 0xF3, + 0x00, 0x01, 0x84, 0xF8, 0x27, 0x10, 0x42, 0x78, 0x92, 0x08, 0x62, 0xF3, 0x41, 0x01, 0x84, 0xF8, + 0x27, 0x10, 0x00, 0xE0, 0xAA, 0xE0, 0x00, 0x78, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, + 0x47, 0xF9, 0x28, 0x68, 0x90, 0xF8, 0xC9, 0x00, 0x01, 0x09, 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, + 0x04, 0x10, 0x20, 0x70, 0xE5, 0x48, 0x01, 0xF0, 0xAE, 0xF8, 0xA4, 0xF8, 0x5E, 0x00, 0x28, 0x68, + 0x10, 0xF8, 0xC8, 0x1F, 0xCA, 0x08, 0xE1, 0x7A, 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, 0x40, 0x78, + 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, 0x20, 0x46, 0x00, 0xF0, + 0xD7, 0xFB, 0x28, 0x68, 0x90, 0xF8, 0xCE, 0x00, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, + 0x0C, 0xF9, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, 0xF0, 0x00, + 0xA0, 0x30, 0x04, 0xF8, 0x0A, 0x09, 0x29, 0x68, 0x11, 0xF8, 0xC8, 0x0F, 0x82, 0x09, 0xE0, 0x7A, + 0x62, 0xF3, 0x00, 0x00, 0xE0, 0x72, 0x0A, 0x78, 0x52, 0x09, 0x62, 0xF3, 0x41, 0x00, 0xE0, 0x72, + 0x4A, 0x79, 0xD2, 0x09, 0x62, 0xF3, 0x82, 0x00, 0xE0, 0x72, 0x08, 0x7C, 0x62, 0x79, 0x60, 0xF3, + 0x04, 0x02, 0x62, 0x71, 0x48, 0x7C, 0x21, 0x79, 0x60, 0xF3, 0x04, 0x01, 0xC4, 0x48, 0x21, 0x71, + 0x94, 0xF8, 0x37, 0x10, 0xC0, 0x79, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x37, 0x10, 0xC1, 0x48, + 0x01, 0xF0, 0x61, 0xF8, 0xA4, 0xF8, 0x52, 0x00, 0x28, 0x68, 0xE1, 0x88, 0xB0, 0xF8, 0xD3, 0x20, + 0x62, 0xF3, 0x0B, 0x01, 0xE1, 0x80, 0x10, 0xF8, 0xCD, 0x1F, 0xCA, 0x08, 0x21, 0x7C, 0x62, 0xF3, + 0x02, 0x01, 0x21, 0x74, 0x10, 0xF8, 0x15, 0x1F, 0xA2, 0x78, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x70, + 0x10, 0xF8, 0x1A, 0x19, 0x0A, 0x09, 0xE1, 0x78, 0x62, 0xF3, 0x03, 0x01, 0xE1, 0x70, 0x01, 0x79, + 0x0A, 0x09, 0x61, 0x78, 0x62, 0xF3, 0x02, 0x01, 0x61, 0x70, 0x81, 0x78, 0x8A, 0x09, 0x21, 0x78, + 0x62, 0xF3, 0x00, 0x01, 0x21, 0x70, 0x01, 0x78, 0xCA, 0x09, 0x21, 0x7B, 0x62, 0xF3, 0x00, 0x01, + 0x21, 0x73, 0x01, 0x79, 0xCA, 0x09, 0x94, 0xF8, 0x37, 0x10, 0x62, 0xF3, 0x45, 0x11, 0x84, 0xF8, + 0x37, 0x10, 0x21, 0x8F, 0x6F, 0xF3, 0x08, 0x01, 0x01, 0xF5, 0x80, 0x71, 0x21, 0x87, 0x00, 0x21, + 0xC4, 0xF8, 0x3A, 0x10, 0x41, 0x79, 0x8A, 0x09, 0xE1, 0x7A, 0x62, 0xF3, 0xC3, 0x01, 0xE1, 0x72, + 0x00, 0x78, 0x00, 0x09, 0x60, 0xF3, 0x04, 0x11, 0xE1, 0x72, 0x38, 0xBD, 0x20, 0xF0, 0x01, 0x00, + 0xD4, 0xE6, 0x10, 0xB5, 0x04, 0x46, 0xA4, 0x22, 0x97, 0x49, 0x02, 0xF0, 0x1B, 0xFF, 0x97, 0x48, + 0xC1, 0x78, 0xA0, 0x89, 0x61, 0xF3, 0x0B, 0x00, 0xA0, 0x81, 0x10, 0xBD, 0x38, 0xB5, 0x04, 0x46, + 0xFF, 0xF7, 0xEF, 0xFF, 0x00, 0xF0, 0xC2, 0xFA, 0x00, 0x22, 0x00, 0x92, 0x02, 0x46, 0x0B, 0x46, + 0x20, 0x46, 0x01, 0xF0, 0xDC, 0xF9, 0x8E, 0x48, 0x00, 0xF0, 0xF5, 0xFF, 0x8D, 0x4D, 0xA4, 0xF8, + 0x7C, 0x00, 0x28, 0x68, 0x90, 0xF8, 0xF8, 0x00, 0xA0, 0x70, 0x28, 0x68, 0x90, 0xF8, 0xF9, 0x00, + 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x01, 0xF0, 0x86, 0xF8, 0x28, 0x68, 0x10, 0xF8, 0xF9, 0x1F, + 0x0A, 0x09, 0xA1, 0x7C, 0x62, 0xF3, 0x01, 0x01, 0xA1, 0x74, 0x02, 0x78, 0x92, 0x09, 0x62, 0xF3, + 0x87, 0x11, 0xA1, 0x74, 0x81, 0x78, 0x94, 0xF8, 0x2D, 0x20, 0x61, 0xF3, 0x04, 0x02, 0x84, 0xF8, + 0x2D, 0x20, 0xC1, 0x78, 0x94, 0xF8, 0x2C, 0x20, 0x61, 0xF3, 0x04, 0x02, 0x84, 0xF8, 0x2C, 0x20, + 0x40, 0x78, 0xA1, 0x7D, 0x60, 0xF3, 0x03, 0x01, 0xA1, 0x75, 0x00, 0x21, 0x20, 0x46, 0x01, 0xF0, + 0xEC, 0xF9, 0x14, 0xF8, 0x5E, 0x0F, 0x20, 0xF0, 0x01, 0x00, 0x04, 0xF8, 0x01, 0x0B, 0x6C, 0x48, + 0x01, 0x79, 0x20, 0x78, 0x61, 0xF3, 0x04, 0x00, 0x04, 0xF8, 0x2F, 0x09, 0x28, 0x68, 0xB0, 0xF8, + 0xFD, 0x10, 0x20, 0x88, 0x61, 0xF3, 0x08, 0x00, 0x20, 0x80, 0x38, 0xBD, 0x70, 0xB5, 0x69, 0x4E, + 0x03, 0x28, 0x34, 0x68, 0x04, 0xF2, 0x5E, 0x62, 0x04, 0xF6, 0x6E, 0x05, 0x14, 0xD0, 0x04, 0x28, + 0x20, 0xD0, 0x94, 0xF8, 0x51, 0x06, 0x94, 0xF8, 0x50, 0x16, 0x02, 0xEB, 0x40, 0x00, 0x00, 0xF0, + 0x96, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0x60, 0x18, 0x90, 0xF8, 0x61, 0x08, 0x05, 0xEB, 0x40, 0x00, + 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, 0xA2, 0xBA, 0x94, 0xF8, 0x53, 0x06, 0x94, 0xF8, 0x52, 0x16, + 0x02, 0xEB, 0x40, 0x00, 0x00, 0xF0, 0x83, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0x62, 0x18, 0x90, 0xF8, + 0x63, 0x08, 0xEB, 0xE7, 0x94, 0xF8, 0x55, 0x06, 0x94, 0xF8, 0x54, 0x16, 0x02, 0xEB, 0x40, 0x00, + 0x00, 0xF0, 0x75, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0x64, 0x18, 0x90, 0xF8, 0x65, 0x08, 0xDD, 0xE7, + 0x2D, 0xE9, 0xF8, 0x43, 0x4C, 0x4D, 0x4F, 0xF0, 0x01, 0x09, 0x00, 0x26, 0x85, 0xF8, 0x00, 0x90, + 0xAE, 0x70, 0x43, 0x4F, 0xDF, 0xF8, 0x1C, 0x81, 0x04, 0x46, 0xEE, 0x70, 0x09, 0x29, 0x72, 0xD2, + 0xDF, 0xE8, 0x01, 0xF0, 0x71, 0x05, 0x09, 0x18, 0x44, 0x2F, 0x48, 0x5E, 0x62, 0x00, 0x20, 0x46, + 0xFF, 0xF7, 0x47, 0xFF, 0x67, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0xB8, 0x78, 0x94, 0xF8, + 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, + 0xFF, 0x00, 0x12, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x34, 0xFF, 0xD8, 0xF8, 0x00, 0x10, 0x91, 0xF8, + 0x01, 0x11, 0xA1, 0x70, 0xF9, 0x78, 0x94, 0xF8, 0x5F, 0x20, 0x61, 0xF3, 0x04, 0x02, 0x84, 0xF8, + 0x5F, 0x20, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x00, 0x01, 0x00, 0xF0, 0x03, 0x00, 0xA8, 0x70, + 0x41, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x1D, 0xFF, 0x00, 0x21, 0x20, 0x46, 0x00, 0xF0, 0xCB, 0xFF, + 0x94, 0xF8, 0x5E, 0x00, 0x20, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, 0x78, 0x79, 0x94, 0xF8, + 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0x17, 0xE0, 0x20, 0x46, 0xFF, 0xF7, + 0x15, 0xFF, 0x28, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x11, 0xFF, 0x00, 0x21, 0x20, 0x46, 0x00, 0xF0, + 0xB2, 0xFF, 0xB8, 0x79, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, + 0x94, 0xF8, 0x5E, 0x00, 0x20, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, 0x2E, 0x70, 0x12, 0xE0, + 0x20, 0x46, 0xFF, 0xF7, 0x83, 0xFD, 0xF9, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0xEA, 0xFE, 0x01, 0x22, + 0x00, 0x23, 0x20, 0x46, 0x00, 0x96, 0x01, 0xF0, 0xDA, 0xF8, 0x20, 0x46, 0x00, 0xF0, 0xAB, 0xFA, + 0x20, 0x46, 0x00, 0xF0, 0x2D, 0xFA, 0x20, 0x46, 0x00, 0xF0, 0xAC, 0xFB, 0x94, 0xF8, 0x27, 0x00, + 0xC0, 0x07, 0x13, 0xD0, 0x6E, 0x70, 0x13, 0xE0, 0xFC, 0x4C, 0x01, 0x20, 0x88, 0x5C, 0x01, 0x20, + 0x4E, 0x7B, 0x01, 0x20, 0xB4, 0x59, 0x01, 0x20, 0x7C, 0x82, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0x24, 0x52, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0xA2, 0x07, 0x10, 0x00, 0x85, 0xF8, 0x01, 0x90, + 0xA0, 0x89, 0xC0, 0xF3, 0x0B, 0x00, 0xE8, 0x80, 0xBD, 0xE8, 0xF8, 0x83, 0x7F, 0xB5, 0x00, 0xF0, + 0x8D, 0xF9, 0xCD, 0xE9, 0x00, 0x01, 0x00, 0xF0, 0x8E, 0xF9, 0xCD, 0xE9, 0x02, 0x01, 0x08, 0x21, + 0x68, 0x46, 0x01, 0xF0, 0x0F, 0xFB, 0x1E, 0x4C, 0x08, 0x21, 0x20, 0x71, 0x02, 0xA8, 0x01, 0xF0, + 0x09, 0xFB, 0x60, 0x71, 0x1B, 0x48, 0x00, 0x21, 0x1A, 0x4D, 0x40, 0xF8, 0x02, 0x1F, 0x01, 0x24, + 0x41, 0x60, 0x01, 0x72, 0xAD, 0x1C, 0xE0, 0xB2, 0xFF, 0xF7, 0xD2, 0xFA, 0x28, 0x55, 0x64, 0x1C, + 0x09, 0x2C, 0xF8, 0xDB, 0x14, 0x48, 0xFF, 0xF7, 0xD9, 0xFB, 0x7F, 0xBD, 0x70, 0xB5, 0x12, 0x4D, + 0x04, 0x79, 0xA4, 0x35, 0x8C, 0xB1, 0x21, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x29, 0xFF, 0xA8, 0x7C, + 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF0, 0xC2, 0xF9, 0x20, 0x46, 0xFF, 0xF7, 0xE7, 0xFE, 0x0B, 0x49, + 0x28, 0x46, 0x01, 0xF0, 0xD5, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0x01, 0x20, 0x70, 0xBD, 0x40, 0xF2, + 0xFF, 0x10, 0xC1, 0xEB, 0x41, 0x21, 0x91, 0xFB, 0xF0, 0xF0, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, + 0xA2, 0x07, 0x10, 0x00, 0x4C, 0x7B, 0x01, 0x20, 0x7C, 0x82, 0x10, 0x00, 0x8F, 0x33, 0x01, 0x00, + 0x10, 0xB5, 0x00, 0xF0, 0x7D, 0xFA, 0xFF, 0xF7, 0xA9, 0xFF, 0xFF, 0xF7, 0x0F, 0xFA, 0xFF, 0xF7, + 0x5B, 0xF9, 0xFE, 0xF7, 0xC2, 0xFC, 0xFE, 0xF7, 0x38, 0xFD, 0x00, 0xF0, 0x8D, 0xFA, 0x7F, 0x49, + 0x00, 0x20, 0x48, 0x60, 0x70, 0x21, 0x7E, 0x48, 0x02, 0xF0, 0xF3, 0xFD, 0x7D, 0x48, 0x04, 0x68, + 0x94, 0xF8, 0xE7, 0x00, 0xC0, 0x06, 0x05, 0xD5, 0x28, 0x22, 0x04, 0xF5, 0x0F, 0x61, 0x78, 0x48, + 0x02, 0xF0, 0x68, 0xFD, 0x94, 0xF8, 0x33, 0x01, 0xC0, 0x06, 0x0F, 0xD5, 0x74, 0x48, 0x20, 0x22, + 0x04, 0xF6, 0x16, 0x11, 0x28, 0x30, 0x02, 0xF0, 0x5D, 0xFD, 0x04, 0xF6, 0x3F, 0x11, 0x70, 0x48, + 0x28, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x48, 0x30, 0x02, 0xF0, 0x54, 0xBD, 0x10, 0xBD, 0x38, 0xB1, + 0x01, 0x28, 0x07, 0xD0, 0x02, 0x28, 0x07, 0xD0, 0x17, 0x20, 0x00, 0x21, 0xFC, 0xF7, 0x97, 0xBA, + 0x14, 0x20, 0xFA, 0xE7, 0x15, 0x20, 0xF8, 0xE7, 0x16, 0x20, 0xF6, 0xE7, 0x00, 0x21, 0x01, 0x60, + 0x41, 0x60, 0x81, 0x60, 0xC1, 0x60, 0x70, 0x47, 0x70, 0xB5, 0x60, 0x4C, 0x62, 0x4D, 0x20, 0x68, + 0x09, 0xE0, 0x00, 0xBF, 0x55, 0xF8, 0x20, 0x10, 0x60, 0x48, 0x88, 0x47, 0x00, 0x28, 0x11, 0xD0, + 0x20, 0x68, 0x40, 0x1C, 0x20, 0x60, 0x07, 0x28, 0xF4, 0xD3, 0x60, 0x68, 0x5B, 0x49, 0x40, 0x1C, + 0x10, 0x31, 0x00, 0x22, 0x60, 0x60, 0x0A, 0x70, 0x48, 0x60, 0x58, 0x48, 0x01, 0x68, 0x10, 0x30, + 0x88, 0x47, 0x01, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0x04, 0x46, 0x00, 0x79, 0x00, 0x25, 0x40, 0xB9, + 0xE0, 0x79, 0x30, 0xB9, 0xA0, 0x79, 0x20, 0xB9, 0x20, 0x7A, 0x10, 0xB9, 0x60, 0x79, 0x00, 0x28, + 0x17, 0xD0, 0x4E, 0x48, 0x34, 0x21, 0x10, 0x30, 0x02, 0xF0, 0xAD, 0xFD, 0x1E, 0xCC, 0x4B, 0x48, + 0x80, 0xE8, 0x1E, 0x00, 0x45, 0x48, 0x05, 0x60, 0x46, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x00, + 0xC0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0x18, 0xFA, 0x02, 0xE0, 0x44, 0x48, 0xFF, 0xF7, 0xBC, 0xFF, + 0x01, 0x20, 0x70, 0xBD, 0x10, 0xB5, 0x01, 0x20, 0x00, 0xF0, 0x62, 0xF8, 0x07, 0x20, 0x00, 0xF0, + 0x5F, 0xF8, 0x08, 0x20, 0x00, 0xF0, 0x5C, 0xF8, 0x05, 0x20, 0x00, 0xF0, 0x59, 0xF8, 0x0D, 0x20, + 0x00, 0xF0, 0x56, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x53, 0xF8, 0x01, 0x20, 0x00, 0xF0, 0x5B, 0xF8, + 0x07, 0x20, 0x00, 0xF0, 0x58, 0xF8, 0x08, 0x20, 0x00, 0xF0, 0x55, 0xF8, 0x05, 0x20, 0x00, 0xF0, + 0x52, 0xF8, 0x0D, 0x20, 0x00, 0xF0, 0x4F, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x4C, 0xF8, 0x02, 0xF0, + 0x86, 0xF9, 0x00, 0xF0, 0xB3, 0xFD, 0x00, 0xF0, 0xDF, 0xF9, 0x01, 0x20, 0x00, 0xF0, 0x2D, 0xF8, + 0x07, 0x20, 0x00, 0xF0, 0x2A, 0xF8, 0x08, 0x20, 0x00, 0xF0, 0x27, 0xF8, 0xBD, 0xE8, 0x10, 0x40, + 0x05, 0x20, 0x00, 0xF0, 0x22, 0xB8, 0x70, 0xB5, 0x20, 0x4C, 0x05, 0x00, 0x0E, 0xD0, 0xFF, 0xF7, + 0xC1, 0xFF, 0x60, 0x68, 0x21, 0x49, 0x40, 0x1C, 0x10, 0x31, 0x60, 0x60, 0x0D, 0x70, 0x48, 0x60, + 0x1E, 0x48, 0x01, 0x68, 0xBD, 0xE8, 0x70, 0x40, 0x10, 0x30, 0x08, 0x47, 0x20, 0x68, 0x40, 0x1C, + 0x20, 0x60, 0xBD, 0xE8, 0x70, 0x40, 0x19, 0x48, 0x66, 0xE7, 0x00, 0xF0, 0x57, 0xB8, 0x00, 0xF0, + 0x5A, 0xB8, 0x00, 0xF0, 0x5D, 0xB8, 0x00, 0xF0, 0x61, 0xB8, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, + 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x00, 0x11, 0x70, 0x47, + 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, + 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, + 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0xAC, 0x07, 0x10, 0x00, + 0x88, 0x5C, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0x4C, 0x6F, 0x01, 0x00, 0xC4, 0x83, 0x10, 0x00, + 0x70, 0xB5, 0x00, 0x23, 0x14, 0x46, 0x09, 0xE0, 0x31, 0xF9, 0x13, 0x50, 0x31, 0xF9, 0x14, 0x60, + 0x35, 0x44, 0x6D, 0x10, 0x20, 0xF8, 0x13, 0x50, 0x5B, 0x1C, 0x64, 0x1C, 0x93, 0x42, 0xF3, 0xDB, + 0x70, 0xBD, 0x30, 0xB4, 0x00, 0x24, 0x4B, 0xB9, 0x0C, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x14, 0x30, + 0x31, 0xF8, 0x14, 0x50, 0x2B, 0x44, 0x20, 0xF8, 0x14, 0x30, 0x64, 0x1C, 0x94, 0x42, 0xF5, 0xDB, + 0x30, 0xBC, 0x70, 0x47, 0x30, 0xBC, 0x52, 0x00, 0x02, 0xF0, 0x4C, 0xBC, 0x99, 0x48, 0x00, 0x68, + 0xC1, 0x6A, 0x80, 0x6A, 0x70, 0x47, 0x97, 0x48, 0x00, 0x68, 0x41, 0x6A, 0x00, 0x6A, 0x70, 0x47, + 0x94, 0x48, 0x00, 0x68, 0x00, 0xF6, 0x38, 0x20, 0x03, 0xC8, 0x70, 0x47, 0x91, 0x48, 0x00, 0x68, + 0x00, 0xF5, 0x23, 0x60, 0x03, 0xC8, 0x70, 0x47, 0xF0, 0xB5, 0x00, 0x24, 0x25, 0x46, 0x8E, 0x4E, + 0x4F, 0xF4, 0x00, 0x67, 0x14, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x15, 0x30, 0xC3, 0xF3, 0x0B, 0x03, + 0x5F, 0xEA, 0xD3, 0x2C, 0x00, 0xD0, 0x33, 0x43, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, 0x9C, 0x42, + 0x00, 0xDA, 0x9C, 0xB2, 0xBC, 0x42, 0x02, 0xD3, 0x40, 0xF2, 0xFF, 0x74, 0x02, 0xE0, 0x6D, 0x1C, + 0x8D, 0x42, 0xE9, 0xDB, 0xD4, 0x40, 0x01, 0x20, 0xA0, 0x40, 0x80, 0xB2, 0xF0, 0xBD, 0x30, 0xB5, + 0x7F, 0x4B, 0x7E, 0x4C, 0x5A, 0x68, 0x82, 0x42, 0x02, 0xD1, 0xDA, 0x68, 0x8A, 0x42, 0x0A, 0xD0, + 0x00, 0x22, 0x06, 0xE0, 0x30, 0xF8, 0x12, 0x50, 0xC5, 0xF3, 0x0B, 0x05, 0x24, 0xF8, 0x12, 0x50, + 0x52, 0x1C, 0x8A, 0x42, 0xF6, 0xDB, 0xD9, 0x60, 0x58, 0x60, 0x30, 0xBD, 0x30, 0xB5, 0x74, 0x4B, + 0x74, 0x4C, 0x9A, 0x68, 0x82, 0x42, 0x02, 0xD1, 0x1A, 0x69, 0x8A, 0x42, 0x0D, 0xD0, 0x00, 0x22, + 0x07, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x12, 0x50, 0xC5, 0xF3, 0x0B, 0x05, 0x24, 0xF8, 0x12, 0x50, + 0x52, 0x1C, 0x8A, 0x42, 0xF6, 0xDB, 0x19, 0x61, 0x98, 0x60, 0x30, 0xBD, 0x70, 0xB5, 0x04, 0x46, + 0x69, 0x48, 0x01, 0x68, 0x02, 0x29, 0x0A, 0xD1, 0x65, 0x4D, 0x29, 0x78, 0x8C, 0x42, 0x06, 0xD0, + 0x00, 0xEB, 0x84, 0x00, 0xD0, 0xF8, 0x9C, 0x00, 0x00, 0xF0, 0xD7, 0xFC, 0x2C, 0x70, 0x70, 0xBD, + 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x28, 0x00, 0x80, 0x06, 0x04, 0xD5, 0x5F, 0x48, 0x00, 0xF0, + 0xBA, 0xFC, 0xA4, 0xF8, 0x8C, 0x00, 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x28, 0x00, + 0x80, 0x06, 0x0A, 0xD5, 0x59, 0x48, 0x28, 0x30, 0x00, 0xF0, 0xAD, 0xFC, 0x24, 0xF8, 0x8E, 0x0F, + 0x56, 0x48, 0x48, 0x30, 0x00, 0xF0, 0xA7, 0xFC, 0x60, 0x80, 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, + 0x90, 0xF8, 0x28, 0x00, 0x80, 0x06, 0x05, 0xD5, 0x50, 0x48, 0x70, 0x30, 0x00, 0xF0, 0x9B, 0xFC, + 0xA4, 0xF8, 0x8E, 0x00, 0x10, 0xBD, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x02, 0x00, 0x4F, 0xF0, + 0x00, 0x00, 0x00, 0xD1, 0x08, 0x46, 0x70, 0x47, 0x02, 0x46, 0x00, 0x20, 0x01, 0x2A, 0x00, 0xD1, + 0x08, 0x46, 0x70, 0x47, 0x3F, 0x49, 0x0A, 0x68, 0x92, 0xF8, 0xB0, 0x20, 0x93, 0x09, 0x10, 0xF8, + 0x3E, 0x2B, 0x63, 0xF3, 0x82, 0x02, 0x00, 0xF8, 0x3E, 0x2C, 0x0B, 0x68, 0x93, 0xF8, 0xB0, 0x30, + 0x5B, 0x09, 0x63, 0xF3, 0x45, 0x12, 0x00, 0xF8, 0x3E, 0x2C, 0x09, 0x68, 0xB1, 0xF8, 0xB7, 0x20, + 0x02, 0x82, 0x91, 0xF8, 0xB6, 0x20, 0x83, 0x7F, 0x62, 0xF3, 0x07, 0x13, 0x83, 0x77, 0x91, 0xF8, + 0xB3, 0x20, 0x13, 0x09, 0x02, 0x7D, 0x63, 0xF3, 0x06, 0x12, 0x02, 0x75, 0x31, 0xF8, 0xB1, 0x3F, + 0x02, 0x8B, 0x63, 0xF3, 0x09, 0x02, 0x02, 0x83, 0x11, 0xF8, 0x01, 0x2C, 0x93, 0x08, 0x82, 0x7D, + 0x63, 0xF3, 0x86, 0x12, 0x82, 0x75, 0x8A, 0x78, 0xC3, 0x7D, 0x62, 0xF3, 0x03, 0x03, 0xC3, 0x75, + 0xB1, 0xF8, 0x03, 0x30, 0xB0, 0xF8, 0x1B, 0x20, 0x63, 0xF3, 0x08, 0x02, 0xA0, 0xF8, 0x1B, 0x20, + 0x09, 0x89, 0x41, 0x82, 0x70, 0x47, 0x10, 0xF8, 0x37, 0x1F, 0x41, 0xF0, 0x10, 0x01, 0x00, 0xF8, + 0x1F, 0x19, 0x30, 0xF8, 0x0C, 0x2C, 0xC1, 0x7E, 0x6F, 0xF3, 0x0B, 0x02, 0x10, 0x32, 0x20, 0xF8, + 0x0C, 0x2C, 0x30, 0xF8, 0x08, 0x2C, 0x21, 0xF0, 0x23, 0x01, 0x6F, 0xF3, 0x0B, 0x02, 0x40, 0x32, + 0x20, 0xF8, 0x08, 0x2C, 0x08, 0x22, 0x00, 0xF8, 0x16, 0x2C, 0x90, 0xF8, 0x47, 0x20, 0x41, 0xF0, + 0x0C, 0x01, 0x22, 0xF0, 0x1F, 0x02, 0x80, 0xF8, 0x47, 0x20, 0x02, 0x8B, 0x6F, 0xF3, 0x08, 0x02, + 0x02, 0x83, 0xC1, 0x76, 0xC1, 0x8A, 0x6F, 0xF3, 0x0B, 0x01, 0x3F, 0x31, 0xC1, 0x82, 0x41, 0x7D, + 0x21, 0xF0, 0x1F, 0x01, 0x41, 0x75, 0x01, 0x7D, 0x21, 0xF0, 0x1F, 0x01, 0x01, 0x75, 0x90, 0xF8, + 0x46, 0x10, 0x21, 0xF0, 0x01, 0x01, 0x80, 0xF8, 0x46, 0x10, 0x01, 0x7C, 0x41, 0xF0, 0x20, 0x01, + 0x01, 0x74, 0x70, 0x47, 0x20, 0x07, 0x10, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xB4, 0x59, 0x01, 0x20, + 0xB4, 0x07, 0x10, 0x00, 0xB4, 0x5B, 0x01, 0x20, 0x08, 0x84, 0x10, 0x00, 0xF8, 0x5B, 0x01, 0x20, + 0x70, 0x47, 0x10, 0xB5, 0x00, 0xF0, 0x93, 0xFE, 0x08, 0xB1, 0x01, 0x20, 0x10, 0xBD, 0x08, 0x48, + 0x00, 0xF0, 0x76, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x06, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x90, 0xF8, + 0x70, 0x00, 0x40, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x77, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x00, + 0x47, 0x3E, 0x01, 0x00, 0x20, 0x07, 0x10, 0x00, 0x7B, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x70, + 0x81, 0x70, 0xC1, 0x70, 0x01, 0x71, 0x70, 0x47, 0x70, 0xB5, 0x0D, 0x20, 0x00, 0xF0, 0xD5, 0xF8, + 0x0D, 0x20, 0x00, 0xF0, 0xDD, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0xCF, 0xF8, 0x0C, 0x20, 0x00, 0xF0, + 0xD7, 0xF8, 0x71, 0x4C, 0x71, 0x48, 0xA5, 0x78, 0xC0, 0x7A, 0xA0, 0x70, 0xEC, 0xF7, 0xC6, 0xF8, + 0xA2, 0x78, 0x01, 0x21, 0x00, 0x20, 0xA2, 0xB1, 0x23, 0x78, 0xAB, 0xB1, 0x95, 0x42, 0x20, 0xD1, + 0x01, 0x2A, 0x1E, 0xD0, 0x02, 0x2A, 0xE2, 0x78, 0x1E, 0xD0, 0x02, 0xB1, 0xE0, 0x70, 0x22, 0x79, + 0x52, 0x1C, 0xD2, 0xB2, 0x22, 0x71, 0x04, 0x2A, 0x1E, 0xD3, 0x20, 0x71, 0xE1, 0x70, 0x04, 0x20, + 0x1B, 0xE0, 0x21, 0x70, 0xE0, 0x70, 0x02, 0xE0, 0x02, 0x22, 0x22, 0x70, 0xE1, 0x70, 0x20, 0x71, + 0xEC, 0xF7, 0xA2, 0xF8, 0xE0, 0x78, 0x60, 0x70, 0xBD, 0xE8, 0x70, 0x40, 0x5B, 0x48, 0xFF, 0xF7, + 0x6B, 0xBD, 0xE1, 0x70, 0x20, 0x71, 0xEA, 0xE7, 0x0A, 0xB1, 0xE0, 0x70, 0x00, 0xE0, 0xE1, 0x70, + 0x20, 0x71, 0xE0, 0x78, 0x00, 0x28, 0xE2, 0xD1, 0x05, 0x20, 0x20, 0x70, 0xBD, 0xE8, 0x70, 0x40, + 0xEC, 0xF7, 0x8A, 0xB8, 0x70, 0xB5, 0x50, 0x4C, 0x20, 0x78, 0x04, 0x28, 0x06, 0xD0, 0x20, 0x78, + 0x00, 0x25, 0x05, 0x28, 0x07, 0xD0, 0x25, 0x70, 0x65, 0x70, 0x70, 0xBD, 0x02, 0x20, 0x20, 0x70, + 0x01, 0x20, 0x60, 0x70, 0x0C, 0xE0, 0x4A, 0x48, 0xA1, 0x78, 0x00, 0x68, 0x02, 0x29, 0x0C, 0xD0, + 0x90, 0xF8, 0xBE, 0x00, 0x47, 0x49, 0x01, 0xF0, 0x0F, 0xFF, 0x03, 0x20, 0x20, 0x70, 0x65, 0x70, + 0xBD, 0xE8, 0x70, 0x40, 0x41, 0x48, 0xFF, 0xF7, 0x37, 0xBD, 0x90, 0xF8, 0xBD, 0x00, 0xF1, 0xE7, + 0x10, 0xB5, 0x0D, 0x20, 0x00, 0xF0, 0x61, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x5E, 0xF8, 0x3A, 0x4C, + 0x3B, 0x49, 0xA0, 0x78, 0x03, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x06, 0xD0, 0x01, 0x28, 0x08, 0xD0, + 0x0D, 0xE0, 0x08, 0x68, 0x90, 0xF8, 0xBE, 0x00, 0x06, 0xE0, 0x08, 0x68, 0x90, 0xF8, 0xBC, 0x00, + 0x02, 0xE0, 0x08, 0x68, 0x90, 0xF8, 0xBB, 0x00, 0x32, 0x49, 0x01, 0xF0, 0xE5, 0xFE, 0x03, 0x20, + 0x20, 0x70, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x2D, 0x4C, 0x07, 0x46, 0x2A, 0x4D, 0x20, 0x68, + 0x4F, 0xF0, 0x00, 0x06, 0x90, 0xF8, 0xB0, 0x10, 0xC9, 0x07, 0x0E, 0xD0, 0x69, 0x78, 0x01, 0x29, + 0x0E, 0xD0, 0xA7, 0xF8, 0x4E, 0x60, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0xF3, 0xC1, 0x00, 0x02, 0x28, + 0x1E, 0xD0, 0x00, 0x21, 0x38, 0x46, 0x00, 0xF0, 0x4F, 0xFB, 0x6E, 0x70, 0xBD, 0xE8, 0xF0, 0x81, + 0x0D, 0x20, 0x00, 0xF0, 0x2D, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x2A, 0xF8, 0x20, 0x68, 0x90, 0xF8, + 0xB0, 0x00, 0xC0, 0xF3, 0xC1, 0x00, 0x02, 0x28, 0x08, 0xD0, 0x0D, 0x20, 0x00, 0xF0, 0x0A, 0xF8, + 0x20, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0xF3, 0xC1, 0x01, 0xE3, 0xE7, 0x0C, 0x20, 0xF5, 0xE7, + 0x02, 0x21, 0xDF, 0xE7, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, + 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x00, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, + 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, + 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, + 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0x00, 0x00, 0xC8, 0x07, 0x10, 0x00, 0xC4, 0x83, 0x10, 0x00, + 0x20, 0x07, 0x10, 0x00, 0x95, 0x42, 0x01, 0x00, 0x46, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x04, 0x01, + 0x01, 0x60, 0x00, 0xF0, 0xFB, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xF6, 0xFF, 0x10, 0xBD, 0x10, 0xB5, + 0xFF, 0xF7, 0xF2, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xEE, 0xFF, 0x10, 0xBD, 0x10, 0xB5, + 0xFF, 0xF7, 0xEA, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x57, 0xBC, 0x10, 0xB5, 0xFF, 0xF7, + 0xE3, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xDC, 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0xDC, 0xFF, + 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x5F, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xD5, 0xFF, 0xBD, 0xE8, + 0x10, 0x40, 0x01, 0xF0, 0xC3, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xCE, 0xFF, 0xBD, 0xE8, 0x10, 0x40, + 0x01, 0xF0, 0x27, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xC7, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, + 0x8D, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xC0, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x05, 0xBF, + 0x10, 0xB5, 0xFF, 0xF7, 0xB9, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x6B, 0xBF, 0x10, 0xB5, + 0xFF, 0xF7, 0xB2, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0xD1, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, + 0xAB, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0x95, 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0xA4, 0xFF, + 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0x6A, 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0x9D, 0xFF, 0xBD, 0xE8, + 0x10, 0x40, 0xFF, 0xF7, 0x15, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, 0x96, 0xFF, 0xBD, 0xE8, 0x10, 0x40, + 0xFF, 0xF7, 0x0E, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, 0x8F, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, + 0x8B, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0xEE, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, 0x84, 0xFF, + 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x80, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x7C, 0xFF, + 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x78, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x74, 0xFF, + 0x10, 0xBD, 0x70, 0x47, 0x10, 0xED, 0x00, 0xE0, 0x0E, 0xB5, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, + 0x02, 0x90, 0x09, 0x48, 0x00, 0xF0, 0x13, 0xFE, 0x68, 0x46, 0x00, 0xF0, 0x14, 0xFE, 0xFC, 0xF7, + 0x38, 0xFD, 0xFC, 0xF7, 0x39, 0xFB, 0x00, 0xF0, 0x31, 0xF8, 0x00, 0x21, 0x47, 0x20, 0xFB, 0xF7, + 0x96, 0xFE, 0x01, 0x20, 0x0E, 0xBD, 0x00, 0x00, 0x10, 0x00, 0x32, 0x02, 0x1A, 0x49, 0x10, 0xB5, + 0x01, 0x20, 0x08, 0x70, 0x19, 0x49, 0x00, 0x20, 0x08, 0x60, 0x19, 0x49, 0x08, 0x60, 0x19, 0x49, + 0x08, 0x60, 0x19, 0x49, 0x08, 0x60, 0x00, 0xF0, 0x7F, 0xF9, 0x00, 0xF0, 0x19, 0xF9, 0x00, 0xF0, + 0x7D, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x12, 0x48, 0x02, 0xF0, 0x31, 0xF8, 0x10, 0x49, + 0x08, 0x60, 0x0E, 0x49, 0x09, 0x68, 0x88, 0x42, 0x07, 0xD0, 0x0B, 0x48, 0x00, 0x78, 0x02, 0x28, + 0x03, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0xEB, 0xF7, 0xC9, 0xBE, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, + 0xEA, 0xFF, 0x05, 0x49, 0x02, 0x20, 0x08, 0x70, 0xEB, 0xF7, 0xA4, 0xFE, 0x4F, 0xF0, 0xFF, 0x30, + 0x10, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00, + 0x20, 0x08, 0x10, 0x00, 0x24, 0x08, 0x10, 0x00, 0x28, 0x08, 0x10, 0x00, 0x70, 0xB5, 0x0D, 0x46, + 0x04, 0x46, 0xC1, 0x69, 0x80, 0x68, 0xCC, 0x22, 0x02, 0xF0, 0x73, 0xF9, 0xE1, 0x69, 0xA0, 0x68, + 0x00, 0x22, 0x08, 0x44, 0x4F, 0xF0, 0x80, 0x71, 0x40, 0xF8, 0x04, 0x1C, 0x21, 0x6A, 0x40, 0xE9, + 0x03, 0x21, 0x40, 0xF8, 0x10, 0x2C, 0x40, 0xF8, 0x14, 0x2C, 0x40, 0xF8, 0x18, 0x2C, 0x40, 0xF8, + 0x1C, 0x2C, 0x4F, 0xF0, 0x0B, 0x31, 0x40, 0xE9, 0x09, 0x15, 0x4F, 0xF0, 0x0A, 0x31, 0x40, 0xF8, + 0x28, 0x1C, 0x4F, 0xF0, 0x09, 0x31, 0x40, 0xF8, 0x2C, 0x1C, 0x4F, 0xF0, 0x08, 0x31, 0x40, 0xF8, + 0x30, 0x1C, 0x4F, 0xF0, 0x07, 0x31, 0x40, 0xF8, 0x34, 0x1C, 0x4F, 0xF0, 0x06, 0x31, 0x40, 0xF8, + 0x38, 0x1C, 0x4F, 0xF0, 0x05, 0x31, 0x40, 0xF8, 0x3C, 0x1C, 0x4F, 0xF0, 0x04, 0x31, 0x40, 0xF8, + 0x40, 0x1D, 0x70, 0xBD, 0x81, 0x69, 0x4F, 0xF0, 0xCC, 0x33, 0x0A, 0x68, 0x9A, 0x42, 0x08, 0xD1, + 0x4A, 0x68, 0x9A, 0x42, 0x05, 0xD1, 0x8A, 0x68, 0x9A, 0x42, 0x02, 0xD1, 0xC9, 0x68, 0x99, 0x42, + 0x02, 0xD0, 0x40, 0x68, 0xFC, 0xF7, 0xE7, 0xBA, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0xA0, 0x21, + 0x49, 0x48, 0x02, 0xF0, 0x50, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x06, 0x46, 0x46, 0x48, + 0x00, 0xEB, 0x06, 0x14, 0xEB, 0xF7, 0x8A, 0xFE, 0x05, 0x46, 0x20, 0x78, 0x28, 0xB1, 0x28, 0x46, + 0xEB, 0xF7, 0x8C, 0xFE, 0x6F, 0xF0, 0x01, 0x00, 0x70, 0xBD, 0x03, 0x20, 0x20, 0x70, 0x00, 0x20, + 0x66, 0x60, 0xE0, 0x60, 0x04, 0xF1, 0x08, 0x00, 0x01, 0xF0, 0x74, 0xFF, 0x28, 0x46, 0xEB, 0xF7, + 0x7D, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x46, 0x36, 0x49, 0x00, 0x25, + 0x01, 0xEB, 0x00, 0x14, 0x2E, 0x46, 0xEB, 0xF7, 0x69, 0xFE, 0x80, 0x46, 0xE0, 0x68, 0x38, 0x43, + 0xE0, 0x60, 0x04, 0xF1, 0x08, 0x00, 0x07, 0x46, 0x01, 0xF0, 0x82, 0xFF, 0x0C, 0xE0, 0xE1, 0x68, + 0xC2, 0x6A, 0x11, 0x42, 0x03, 0xD0, 0x00, 0xF0, 0x0F, 0xF9, 0x01, 0x26, 0x00, 0xE0, 0x6D, 0x1C, + 0x29, 0x46, 0x38, 0x46, 0x01, 0xF0, 0x6A, 0xFF, 0x00, 0x28, 0xF0, 0xD1, 0x0E, 0xB1, 0xFF, 0xF7, + 0x3A, 0xFF, 0x40, 0x46, 0xEB, 0xF7, 0x52, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x70, 0xB5, + 0x0D, 0x46, 0x21, 0x49, 0x01, 0xEB, 0x00, 0x14, 0xEB, 0xF7, 0x40, 0xFE, 0xE1, 0x68, 0xA9, 0x43, + 0xE1, 0x60, 0xEB, 0xF7, 0x43, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0x0C, 0x46, 0x1A, 0x49, + 0x01, 0xEB, 0x00, 0x15, 0x00, 0x20, 0x20, 0x60, 0xEB, 0xF7, 0x30, 0xFE, 0xE9, 0x68, 0x21, 0x60, + 0xEB, 0xF7, 0x34, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x46, 0x12, 0x49, + 0x1E, 0x46, 0x90, 0x46, 0x01, 0xEB, 0x00, 0x14, 0xEB, 0xF7, 0x20, 0xFE, 0x07, 0x46, 0x0F, 0x48, + 0x00, 0x68, 0xC5, 0x62, 0xE1, 0x68, 0x29, 0x42, 0x03, 0xD1, 0x04, 0xF1, 0x08, 0x01, 0x00, 0xF0, + 0xDD, 0xF8, 0x38, 0x46, 0xEB, 0xF7, 0x1A, 0xFE, 0xEB, 0xF7, 0x10, 0xFE, 0xE1, 0x68, 0x29, 0x40, + 0x31, 0x60, 0xB8, 0xF1, 0x01, 0x0F, 0x02, 0xD1, 0xE1, 0x68, 0xA9, 0x43, 0xE1, 0x60, 0xEB, 0xF7, + 0x0D, 0xFE, 0x00, 0x20, 0xB9, 0xE7, 0x00, 0x00, 0xB4, 0x84, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00, + 0x10, 0xB5, 0xC8, 0x21, 0x2E, 0x48, 0x02, 0xF0, 0xB6, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, + 0xF0, 0x41, 0x06, 0x46, 0x2A, 0x49, 0x00, 0xEB, 0x86, 0x00, 0x17, 0x46, 0x01, 0xEB, 0x80, 0x04, + 0xEB, 0xF7, 0xEC, 0xFD, 0x05, 0x46, 0x20, 0x78, 0x30, 0xB1, 0x28, 0x46, 0xEB, 0xF7, 0xEE, 0xFD, + 0x6F, 0xF0, 0x01, 0x00, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x20, 0x20, 0x70, 0x00, 0x20, 0x66, 0x60, + 0xC4, 0xE9, 0x02, 0x70, 0x04, 0xF1, 0x10, 0x00, 0x01, 0xF0, 0xD4, 0xFE, 0x28, 0x46, 0xEB, 0xF7, + 0xDD, 0xFD, 0x00, 0x20, 0xEE, 0xE7, 0x70, 0xB5, 0x19, 0x49, 0x00, 0xEB, 0x80, 0x00, 0x01, 0xEB, + 0x80, 0x04, 0xEB, 0xF7, 0xCB, 0xFD, 0x05, 0x46, 0xD4, 0xE9, 0x02, 0x01, 0x81, 0x42, 0x05, 0xDB, + 0x14, 0x48, 0x04, 0xF1, 0x10, 0x01, 0x00, 0x68, 0x00, 0xF0, 0x88, 0xF8, 0xE0, 0x68, 0x40, 0x1C, + 0xE0, 0x60, 0x28, 0x46, 0xEB, 0xF7, 0xC2, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0x0C, 0x49, + 0x00, 0xEB, 0x80, 0x00, 0x01, 0xEB, 0x80, 0x04, 0xEB, 0xF7, 0xB0, 0xFD, 0x05, 0x46, 0xE0, 0x68, + 0x08, 0xB1, 0x40, 0x1E, 0xE0, 0x60, 0x04, 0xF1, 0x10, 0x00, 0x01, 0xF0, 0xC9, 0xFE, 0x10, 0xB1, + 0x20, 0x69, 0x00, 0xF0, 0x11, 0xF8, 0x28, 0x46, 0xEB, 0xF7, 0xA8, 0xFD, 0x00, 0x20, 0x70, 0xBD, + 0x54, 0x85, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0xF0, 0x71, 0x3C, 0x48, + 0x02, 0xF0, 0x51, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x24, 0x00, + 0x02, 0x28, 0x0B, 0xD0, 0x20, 0x46, 0x01, 0xF0, 0xAD, 0xFE, 0x02, 0x20, 0x84, 0xF8, 0x24, 0x00, + 0x34, 0x49, 0x20, 0x46, 0x01, 0xF0, 0x82, 0xFE, 0xFF, 0xF7, 0x6D, 0xFE, 0x00, 0x20, 0x10, 0xBD, + 0x2D, 0xE9, 0xF0, 0x5F, 0x06, 0x46, 0x0A, 0xA8, 0x06, 0xEB, 0x46, 0x01, 0x90, 0xE8, 0x00, 0x0E, + 0x2B, 0x48, 0x1D, 0x46, 0x00, 0xEB, 0x01, 0x14, 0x90, 0x46, 0x20, 0x78, 0x18, 0xB1, 0x6F, 0xF0, + 0x01, 0x00, 0xBD, 0xE8, 0xF0, 0x9F, 0xEB, 0xF7, 0x69, 0xFD, 0x07, 0x46, 0x01, 0x20, 0x20, 0x70, + 0xC4, 0xF8, 0x14, 0x80, 0xC4, 0xE9, 0x01, 0x65, 0x04, 0xF1, 0x18, 0x01, 0x00, 0x20, 0x81, 0xE8, + 0x20, 0x06, 0x84, 0xF8, 0x24, 0x00, 0xE0, 0x60, 0x20, 0x61, 0xC4, 0xE9, 0x0A, 0x80, 0x59, 0x46, + 0x20, 0x46, 0xFF, 0xF7, 0x6B, 0xFE, 0xA0, 0x60, 0x20, 0x46, 0xFF, 0xF7, 0xBD, 0xFF, 0x38, 0x46, + 0xEB, 0xF7, 0x54, 0xFD, 0x00, 0x20, 0xDC, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x24, 0x00, + 0x02, 0x28, 0x09, 0xD0, 0x20, 0x46, 0x01, 0xF0, 0x65, 0xFE, 0x02, 0x20, 0x84, 0xF8, 0x24, 0x00, + 0x10, 0x49, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x04, 0x46, + 0x90, 0xF8, 0x24, 0x00, 0x0D, 0x46, 0x02, 0x28, 0x0B, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0x52, 0xFE, + 0x03, 0x20, 0x84, 0xF8, 0x24, 0x00, 0x29, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x27, 0xFE, 0xFF, 0xF7, + 0x12, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x04, 0x48, 0x00, 0x68, 0x40, 0x68, 0x70, 0x47, 0x00, 0x00, + 0x1C, 0x86, 0x10, 0x00, 0x24, 0x08, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00, 0x6D, 0x48, 0x00, 0x21, + 0x01, 0x60, 0x01, 0x22, 0x02, 0x60, 0x01, 0x60, 0x70, 0x47, 0x10, 0xB5, 0xFF, 0xF7, 0xF6, 0xFF, + 0x69, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x60, 0x00, 0xF0, 0xF5, 0xF9, 0xBD, 0xE8, 0x10, 0x40, + 0x00, 0xF0, 0xD7, 0xBA, 0x01, 0xF0, 0xBF, 0xBC, 0x01, 0xF0, 0x2A, 0xBD, 0x10, 0xB5, 0x01, 0xF0, + 0x27, 0xFD, 0x01, 0xF0, 0xB8, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0xE6, 0xE7, 0xA4, 0x22, 0x5F, 0x49, + 0x01, 0xF0, 0x10, 0xBF, 0x70, 0x47, 0x10, 0xB5, 0x04, 0x46, 0x80, 0x07, 0x02, 0xD0, 0x02, 0x20, + 0xFF, 0xF7, 0xB5, 0xF9, 0x4F, 0xF4, 0x80, 0x30, 0x20, 0x44, 0xC0, 0xF3, 0x4F, 0x00, 0x10, 0xBD, + 0x01, 0x46, 0x98, 0x22, 0x56, 0x48, 0x01, 0xF0, 0xFD, 0xBE, 0x55, 0x4A, 0x00, 0x21, 0x42, 0xF8, + 0x21, 0x00, 0x49, 0x1C, 0x26, 0x29, 0xFA, 0xDB, 0x70, 0x47, 0x01, 0xF0, 0xDE, 0xBC, 0x01, 0xF0, + 0x5C, 0xBC, 0x4D, 0x48, 0x10, 0xB5, 0x40, 0x68, 0x10, 0xB1, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x47, + 0x00, 0x20, 0xFF, 0xF7, 0x94, 0xF9, 0x10, 0xBD, 0x06, 0x29, 0x37, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, + 0x11, 0x24, 0x37, 0x24, 0x36, 0x03, 0x01, 0x78, 0x21, 0xF0, 0x12, 0x01, 0x00, 0xF8, 0x4D, 0x1B, + 0x01, 0x78, 0x21, 0xF0, 0x03, 0x01, 0x00, 0xF8, 0x07, 0x1B, 0x01, 0x78, 0x21, 0xF0, 0x80, 0x01, + 0x0C, 0xE0, 0x01, 0x78, 0x21, 0xF0, 0x02, 0x01, 0x41, 0xF0, 0x10, 0x01, 0x00, 0xF8, 0x4D, 0x1B, + 0x01, 0x78, 0x21, 0xF0, 0x03, 0x01, 0x00, 0xF8, 0x07, 0x1B, 0x12, 0xE0, 0x00, 0xF8, 0x44, 0x1B, + 0x01, 0x78, 0x21, 0xF0, 0x01, 0x01, 0x10, 0xE0, 0x02, 0x78, 0x01, 0x29, 0x42, 0xF0, 0x12, 0x02, + 0x02, 0x70, 0x00, 0xD0, 0x03, 0x21, 0x10, 0xF8, 0x4D, 0x2F, 0x61, 0xF3, 0x01, 0x02, 0x00, 0xF8, + 0x07, 0x2B, 0x01, 0x78, 0x41, 0xF0, 0x80, 0x01, 0xE8, 0xE7, 0x01, 0x70, 0x70, 0x47, 0x01, 0x78, + 0x21, 0xF0, 0x02, 0x01, 0x41, 0xF0, 0x10, 0x01, 0x00, 0xF8, 0x4D, 0x1B, 0x01, 0x78, 0x21, 0xF0, + 0x03, 0x01, 0x89, 0x1C, 0x00, 0xF8, 0x07, 0x1B, 0x01, 0x78, 0x41, 0xF0, 0x80, 0x01, 0x00, 0xF8, + 0x44, 0x1B, 0x01, 0x78, 0x41, 0xF0, 0x01, 0x01, 0xE7, 0xE7, 0x90, 0xF8, 0x29, 0x20, 0x02, 0x29, + 0x04, 0xD0, 0x03, 0x29, 0x22, 0xF0, 0x40, 0x01, 0x02, 0xD1, 0x04, 0xE0, 0x42, 0xF0, 0x40, 0x01, + 0x21, 0xF0, 0x80, 0x01, 0x01, 0xE0, 0x41, 0xF0, 0x80, 0x01, 0x80, 0xF8, 0x29, 0x10, 0x70, 0x47, + 0x90, 0xF8, 0x29, 0x20, 0x01, 0x29, 0x04, 0xD0, 0x02, 0x29, 0x07, 0xD0, 0x22, 0xF0, 0x10, 0x01, + 0x01, 0xE0, 0x42, 0xF0, 0x10, 0x01, 0x21, 0xF0, 0x20, 0x01, 0x01, 0xE0, 0x42, 0xF0, 0x30, 0x01, + 0x80, 0xF8, 0x29, 0x10, 0x70, 0x47, 0xC2, 0x78, 0x00, 0x29, 0x61, 0xF3, 0x03, 0x02, 0xC2, 0x70, + 0x04, 0xD0, 0x10, 0xF8, 0x5E, 0x1F, 0x41, 0xF0, 0x04, 0x01, 0x01, 0x70, 0x70, 0x47, 0xC2, 0x7A, + 0x01, 0x29, 0x61, 0xF3, 0x03, 0x02, 0xC2, 0x72, 0x02, 0xD9, 0x42, 0xF0, 0x10, 0x01, 0xC1, 0x72, + 0x70, 0x47, 0x00, 0x00, 0x90, 0x04, 0x00, 0x22, 0xD0, 0x07, 0x10, 0x00, 0x68, 0x6F, 0x01, 0x00, + 0xA4, 0x00, 0x03, 0x20, 0x01, 0xEB, 0x81, 0x01, 0x02, 0xEB, 0xC1, 0x01, 0x40, 0x5C, 0x01, 0x06, + 0x02, 0xD5, 0x00, 0xF0, 0x7F, 0x00, 0x40, 0x42, 0x70, 0x47, 0x00, 0x2B, 0x04, 0xDA, 0x5B, 0x42, + 0xDB, 0xB2, 0x43, 0xF0, 0x80, 0x03, 0x01, 0xE0, 0x03, 0xF0, 0x7F, 0x03, 0x01, 0xEB, 0x81, 0x01, + 0x02, 0xEB, 0xC1, 0x01, 0x43, 0x54, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x5F, 0x00, 0x25, 0xDD, 0xE9, + 0x0A, 0x78, 0x91, 0x46, 0x9A, 0x46, 0x83, 0x46, 0x2E, 0x46, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, + 0x01, 0xF0, 0xF1, 0xFD, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0A, 0x01, 0x08, 0x43, 0x14, 0xD0, + 0x00, 0x24, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x01, 0xF0, 0xE5, 0xFD, 0x38, 0x40, 0x01, 0xEA, + 0x08, 0x01, 0x08, 0x43, 0x05, 0xD0, 0x00, 0x23, 0x22, 0x46, 0x31, 0x46, 0x58, 0x46, 0xFF, 0xF7, + 0xCC, 0xFF, 0x64, 0x1C, 0x28, 0x2C, 0xEC, 0xDB, 0x76, 0x1C, 0x6D, 0x1C, 0x38, 0x2D, 0xDC, 0xDB, + 0xBD, 0xE8, 0xF0, 0x9F, 0x40, 0x5C, 0x01, 0x06, 0x02, 0xD5, 0x00, 0xF0, 0x7F, 0x00, 0x40, 0x42, + 0x70, 0x47, 0x00, 0x2A, 0x04, 0xDA, 0x52, 0x42, 0xD2, 0xB2, 0x42, 0xF0, 0x80, 0x02, 0x01, 0xE0, + 0x02, 0xF0, 0x7F, 0x02, 0x42, 0x54, 0x70, 0x47, 0xF0, 0xB5, 0x00, 0x24, 0x15, 0x46, 0x0E, 0x46, + 0x84, 0x46, 0x23, 0x46, 0x01, 0x27, 0x0F, 0xE0, 0x06, 0xEB, 0xE3, 0x00, 0x03, 0xF0, 0x07, 0x01, + 0x00, 0x78, 0x07, 0xFA, 0x01, 0xF2, 0x02, 0x42, 0x05, 0xD0, 0x00, 0x22, 0x19, 0x46, 0x60, 0x46, + 0xFF, 0xF7, 0xDF, 0xFF, 0x64, 0x1C, 0x5B, 0x1C, 0xAC, 0x42, 0xED, 0xDB, 0xF0, 0xBD, 0x40, 0x5C, + 0x70, 0x47, 0x42, 0x54, 0x70, 0x47, 0xF0, 0xB5, 0x00, 0x24, 0x23, 0x46, 0x01, 0x26, 0x0D, 0xE0, + 0x01, 0xEB, 0xE3, 0x05, 0x03, 0xF0, 0x07, 0x07, 0x2D, 0x78, 0x06, 0xFA, 0x07, 0xFC, 0x1C, 0xEA, + 0x05, 0x0F, 0x02, 0xD0, 0x00, 0x25, 0xC5, 0x54, 0x64, 0x1C, 0x5B, 0x1C, 0x94, 0x42, 0xEF, 0xDB, + 0xF0, 0xBD, 0x40, 0x5C, 0x70, 0x47, 0x42, 0x54, 0x70, 0x47, 0x40, 0x5C, 0x70, 0x47, 0x42, 0x54, + 0x70, 0x47, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x33, 0x4C, 0x54, 0xF8, 0x3C, 0x8F, 0x67, 0x68, + 0xE6, 0x68, 0x25, 0x7C, 0xDF, 0xF8, 0xC4, 0x90, 0x01, 0x21, 0xC9, 0xF8, 0x00, 0x10, 0x4F, 0xF4, + 0x20, 0x70, 0xEB, 0xF7, 0x9D, 0xFB, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x10, 0xC4, 0xF8, 0x00, 0x80, + 0x67, 0x60, 0xE6, 0x60, 0x25, 0x74, 0xBD, 0xE8, 0xF0, 0x87, 0x27, 0x48, 0x00, 0x21, 0xC1, 0x63, + 0x01, 0x64, 0x81, 0x64, 0x80, 0xF8, 0x4C, 0x10, 0x70, 0x47, 0x70, 0xB5, 0x00, 0x24, 0x0D, 0x46, + 0x02, 0x46, 0x01, 0x20, 0x21, 0x46, 0x01, 0xF0, 0x56, 0xFD, 0x35, 0xB3, 0x1E, 0x4A, 0x48, 0x32, + 0x10, 0x60, 0x11, 0x71, 0xFF, 0xF7, 0xCE, 0xFF, 0x00, 0x20, 0x00, 0xF0, 0x23, 0xF8, 0x00, 0xB1, + 0x01, 0x24, 0xFF, 0xF7, 0xC7, 0xFF, 0x01, 0x20, 0x00, 0xF0, 0x1C, 0xF8, 0x08, 0xB1, 0x44, 0xF0, + 0x02, 0x04, 0xFF, 0xF7, 0xBF, 0xFF, 0x02, 0x20, 0x00, 0xF0, 0x14, 0xF8, 0x08, 0xB1, 0x44, 0xF0, + 0x04, 0x04, 0xFF, 0xF7, 0xB7, 0xFF, 0x03, 0x20, 0x00, 0xF0, 0x0C, 0xF8, 0x08, 0xB1, 0x44, 0xF0, + 0x08, 0x04, 0xFF, 0xF7, 0xAF, 0xFF, 0x20, 0x46, 0x70, 0xBD, 0x0B, 0x4A, 0x3C, 0x32, 0xC2, 0xE9, + 0x00, 0x01, 0xD7, 0xE7, 0x40, 0xF0, 0x20, 0x01, 0x07, 0x48, 0x10, 0xB5, 0x80, 0xF8, 0xA3, 0x10, + 0xE5, 0x21, 0x81, 0x71, 0x4F, 0xF4, 0x20, 0x70, 0xEB, 0xF7, 0x4A, 0xFB, 0x04, 0x48, 0xD0, 0xF8, + 0xC0, 0x02, 0xC0, 0xB2, 0x10, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x68, 0x14, 0x60, 0x22, + 0x00, 0x10, 0x60, 0x22, 0x4E, 0x48, 0x01, 0x68, 0x00, 0x29, 0x01, 0xD0, 0x01, 0x20, 0x08, 0x47, + 0x70, 0x47, 0x10, 0xB5, 0xFF, 0xF7, 0x20, 0xFE, 0x4A, 0x49, 0x02, 0x20, 0x08, 0x70, 0x4A, 0x49, + 0x00, 0x20, 0x08, 0x60, 0x46, 0x48, 0x01, 0x68, 0x00, 0x29, 0x03, 0xD0, 0xBD, 0xE8, 0x10, 0x40, + 0x00, 0x20, 0x08, 0x47, 0x10, 0xBD, 0x42, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x7F, 0xB5, + 0x04, 0x46, 0x03, 0x99, 0x08, 0x9D, 0xC1, 0xF3, 0x14, 0x01, 0x03, 0x91, 0x08, 0x21, 0x02, 0xA8, + 0x00, 0xF0, 0x60, 0xFA, 0x01, 0x2D, 0x02, 0xD0, 0x02, 0x2D, 0x04, 0xD0, 0x06, 0xE0, 0xC0, 0x1C, + 0x20, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0xC0, 0x1D, 0x20, 0xF0, 0x03, 0x00, 0xDD, 0xE9, 0x02, 0x12, + 0x44, 0xF8, 0x3C, 0x1F, 0x62, 0x60, 0x21, 0x7A, 0x60, 0xF3, 0x06, 0x01, 0x21, 0x72, 0x7F, 0xBD, + 0x01, 0x23, 0x40, 0xF8, 0x3C, 0x3F, 0x00, 0x23, 0x43, 0x60, 0x51, 0x43, 0x02, 0x7A, 0x61, 0xF3, + 0x06, 0x02, 0x02, 0x72, 0x70, 0x47, 0x1F, 0xB5, 0x04, 0x46, 0x03, 0x99, 0x02, 0xA8, 0x01, 0xF0, + 0x3F, 0x01, 0x03, 0x91, 0x08, 0x21, 0x00, 0xF0, 0x35, 0xFA, 0xDD, 0xE9, 0x02, 0x12, 0xA1, 0x64, + 0x84, 0xF8, 0x4C, 0x20, 0x14, 0xF8, 0x70, 0x1F, 0x60, 0xF3, 0x05, 0x01, 0x04, 0xF8, 0x1E, 0x19, + 0xE1, 0x7F, 0x60, 0xF3, 0x05, 0x01, 0xE1, 0x77, 0x1F, 0xBD, 0x08, 0xB5, 0x1F, 0xA2, 0x12, 0x68, + 0x00, 0x92, 0x1D, 0xF8, 0x01, 0x20, 0x10, 0xF8, 0x5D, 0x1F, 0x62, 0xF3, 0x01, 0x01, 0x01, 0x70, + 0x08, 0xBD, 0x18, 0x49, 0x03, 0x20, 0x08, 0x70, 0x17, 0x49, 0x19, 0x48, 0x08, 0x60, 0x19, 0x49, + 0x01, 0x20, 0xC1, 0xF8, 0xC0, 0x00, 0x18, 0x49, 0x4F, 0xF4, 0xFA, 0x70, 0xFF, 0xF7, 0xD5, 0xBD, + 0x10, 0xB5, 0x0A, 0x46, 0x81, 0x79, 0x21, 0xF0, 0x0D, 0x01, 0x41, 0xF0, 0xE0, 0x01, 0x81, 0x71, + 0x0B, 0x49, 0x0A, 0x60, 0x0B, 0x4A, 0x03, 0x21, 0x11, 0x70, 0x0B, 0x4A, 0x0C, 0x49, 0x11, 0x60, + 0x01, 0x46, 0xA4, 0x22, 0x0D, 0x48, 0x01, 0xF0, 0xB5, 0xFC, 0x0A, 0x49, 0x01, 0x20, 0xC1, 0xF8, + 0xC0, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x49, 0x4F, 0xF4, 0xFA, 0x70, 0xFF, 0xF7, 0xB5, 0xBD, + 0xD8, 0x07, 0x10, 0x00, 0xD0, 0x07, 0x10, 0x00, 0xD4, 0x07, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x43, 0x4D, 0x01, 0x00, 0x00, 0x00, 0x60, 0x22, 0x35, 0x4D, 0x01, 0x00, 0x00, 0x00, 0x03, 0x20, + 0x16, 0x48, 0x01, 0x78, 0x01, 0x29, 0x08, 0xD1, 0x02, 0x21, 0x01, 0x70, 0x14, 0x48, 0x01, 0x68, + 0x19, 0xB1, 0x00, 0x22, 0x02, 0x60, 0x10, 0x46, 0x08, 0x47, 0x01, 0x20, 0xFE, 0xF7, 0x37, 0xBF, + 0x0E, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x0E, 0x49, 0x08, 0x60, 0x0E, 0x49, 0xE8, 0x20, 0x88, 0x71, + 0x0D, 0x49, 0x0C, 0x20, 0xFF, 0xF7, 0x8B, 0xBD, 0x0A, 0x49, 0x08, 0x20, 0x88, 0x71, 0x0B, 0x49, + 0x00, 0x20, 0x08, 0x62, 0x05, 0x49, 0x08, 0x70, 0x05, 0x49, 0x08, 0x60, 0x70, 0x47, 0x03, 0x48, + 0x00, 0x78, 0x00, 0x28, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0xD0, 0x07, 0x10, 0x00, + 0xDC, 0x07, 0x10, 0x00, 0x00, 0x00, 0x03, 0x20, 0x91, 0x4E, 0x01, 0x00, 0x00, 0x00, 0x60, 0x22, + 0x63, 0x48, 0x01, 0x68, 0x00, 0x29, 0x01, 0xD0, 0x01, 0x20, 0x08, 0x47, 0x70, 0x47, 0x10, 0xB5, + 0xFF, 0xF7, 0x3A, 0xFD, 0x5F, 0x49, 0x02, 0x20, 0x08, 0x70, 0x5F, 0x49, 0x00, 0x20, 0x08, 0x60, + 0x5B, 0x48, 0x01, 0x68, 0x00, 0x29, 0x03, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x08, 0x47, + 0x10, 0xBD, 0x57, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x7F, 0xB5, 0x04, 0x46, 0x03, 0x99, + 0x08, 0x9D, 0xC1, 0xF3, 0x14, 0x01, 0x03, 0x91, 0x08, 0x21, 0x02, 0xA8, 0x00, 0xF0, 0x7A, 0xF9, + 0xDD, 0xE9, 0x02, 0x12, 0xE1, 0x63, 0x22, 0x64, 0x94, 0xF8, 0x44, 0x20, 0xC1, 0xB2, 0x61, 0xF3, + 0x06, 0x02, 0x84, 0xF8, 0x44, 0x20, 0x0A, 0x2D, 0x0F, 0xD0, 0x0B, 0x2D, 0x0D, 0xD0, 0x14, 0xF8, + 0x72, 0x0F, 0x61, 0xF3, 0x05, 0x00, 0x20, 0x70, 0x60, 0x78, 0x61, 0xF3, 0x05, 0x00, 0x60, 0x70, + 0xA0, 0x78, 0x20, 0xF0, 0x08, 0x00, 0xA0, 0x70, 0x7F, 0xBD, 0x14, 0xF8, 0x72, 0x1F, 0x40, 0x1C, + 0x60, 0xF3, 0x05, 0x01, 0x21, 0x70, 0x61, 0x78, 0x60, 0xF3, 0x05, 0x01, 0x61, 0x70, 0xA0, 0x78, + 0x40, 0xF0, 0x08, 0x00, 0xEF, 0xE7, 0x1F, 0xB5, 0x04, 0x46, 0x03, 0x99, 0x02, 0xA8, 0x01, 0xF0, + 0x3F, 0x01, 0x03, 0x91, 0x08, 0x21, 0x00, 0xF0, 0x45, 0xF9, 0xDD, 0xE9, 0x02, 0x12, 0xA1, 0x64, + 0x84, 0xF8, 0x4C, 0x20, 0x14, 0xF8, 0x70, 0x1F, 0x60, 0xF3, 0x05, 0x01, 0x04, 0xF8, 0x1E, 0x19, + 0xE1, 0x7F, 0x60, 0xF3, 0x05, 0x01, 0xE1, 0x77, 0x1F, 0xBD, 0x30, 0xB5, 0x2F, 0xA2, 0x8C, 0xB0, + 0x3C, 0xCA, 0x8D, 0xE8, 0x3C, 0x00, 0x31, 0xA2, 0x0D, 0xF1, 0x10, 0x0C, 0x3C, 0xCA, 0x8C, 0xE8, + 0x3C, 0x00, 0x32, 0xA2, 0x0D, 0xF1, 0x20, 0x0C, 0x3C, 0xCA, 0x8C, 0xE8, 0x3C, 0x00, 0x04, 0xAA, + 0x53, 0x5C, 0x42, 0x7E, 0x63, 0xF3, 0x05, 0x02, 0x42, 0x76, 0x1D, 0xF8, 0x01, 0x30, 0x02, 0x7E, + 0x63, 0xF3, 0x42, 0x02, 0x02, 0x76, 0x08, 0xAA, 0x52, 0x5C, 0x81, 0x79, 0x62, 0xF3, 0x83, 0x01, + 0x81, 0x71, 0x0C, 0xB0, 0x30, 0xBD, 0x1B, 0x49, 0x04, 0x20, 0x08, 0x70, 0x1A, 0x49, 0x27, 0x48, + 0x08, 0x60, 0x27, 0x49, 0x01, 0x20, 0xC1, 0xF8, 0xC0, 0x00, 0x26, 0x49, 0x4F, 0xF4, 0xFA, 0x70, + 0xFF, 0xF7, 0xCB, 0xBC, 0x10, 0xB5, 0x0A, 0x46, 0xB0, 0xF8, 0x56, 0x10, 0x41, 0xF0, 0x01, 0x01, + 0xA0, 0xF8, 0x56, 0x10, 0x81, 0x79, 0x21, 0xF0, 0x01, 0x01, 0x41, 0xF0, 0xE0, 0x01, 0x81, 0x71, + 0x0B, 0x49, 0x0A, 0x60, 0x0B, 0x4A, 0x04, 0x21, 0x11, 0x70, 0x0B, 0x4A, 0x17, 0x49, 0x11, 0x60, + 0x01, 0x46, 0xA4, 0x22, 0x18, 0x48, 0x01, 0xF0, 0xA5, 0xFB, 0x15, 0x49, 0x01, 0x20, 0xC1, 0xF8, + 0xC0, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0x49, 0x4F, 0xF4, 0xFA, 0x70, 0xFF, 0xF7, 0xA5, 0xBC, + 0xE0, 0x07, 0x10, 0x00, 0xD0, 0x07, 0x10, 0x00, 0xD4, 0x07, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, + 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x02, 0x03, 0x02, 0x03, + 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x0F, 0x4F, 0x01, 0x00, + 0x00, 0x00, 0x60, 0x22, 0x01, 0x4F, 0x01, 0x00, 0x00, 0x00, 0x03, 0x20, 0x44, 0x49, 0x01, 0x20, + 0x08, 0x60, 0x17, 0x22, 0x41, 0x07, 0x01, 0xF8, 0x27, 0x2F, 0x0B, 0x22, 0x81, 0xF8, 0x41, 0x20, + 0x3F, 0x49, 0x18, 0x39, 0x08, 0x60, 0x4F, 0xF0, 0x08, 0x51, 0xC1, 0xF8, 0xC4, 0x03, 0x3C, 0x4B, + 0x00, 0x22, 0xB0, 0x33, 0x1A, 0x60, 0x3B, 0x4A, 0x10, 0x60, 0x12, 0x1D, 0x10, 0x60, 0x38, 0x4A, + 0x94, 0x3A, 0x10, 0x60, 0xC1, 0xF8, 0x74, 0x03, 0x70, 0x47, 0x35, 0x49, 0x01, 0x20, 0x94, 0x39, + 0x08, 0x60, 0x70, 0x47, 0x32, 0x49, 0x00, 0x20, 0x94, 0x39, 0x08, 0x60, 0x70, 0x47, 0x4F, 0xF0, + 0x00, 0x50, 0x00, 0x88, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x50, 0x80, 0x78, 0x70, 0x47, 0x4F, 0xF0, + 0x00, 0x51, 0x48, 0x60, 0x70, 0x47, 0x2C, 0x49, 0x02, 0x68, 0x0A, 0x60, 0x42, 0x68, 0x4A, 0x60, + 0x80, 0x68, 0x88, 0x60, 0x70, 0x47, 0x28, 0x49, 0x0A, 0x68, 0x02, 0x60, 0x4A, 0x68, 0x42, 0x60, + 0x89, 0x68, 0x81, 0x60, 0x70, 0x47, 0x22, 0x49, 0x01, 0x20, 0x30, 0x39, 0x08, 0x60, 0x70, 0x47, + 0x4F, 0xF0, 0x00, 0x50, 0x10, 0xF8, 0x22, 0x1F, 0x21, 0xF0, 0x03, 0x01, 0x01, 0x70, 0x70, 0x47, + 0x4F, 0xF0, 0x00, 0x53, 0x03, 0xF8, 0x1F, 0x0F, 0x59, 0x70, 0x98, 0x78, 0x62, 0xF3, 0x03, 0x00, + 0x98, 0x70, 0x70, 0x47, 0x19, 0x48, 0x00, 0x68, 0x70, 0x47, 0x18, 0x49, 0x08, 0x60, 0x70, 0x47, + 0x10, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0xE2, 0x7E, 0x20, 0x23, 0x22, 0xF0, 0xAF, 0x02, 0x03, 0xEA, + 0x40, 0x13, 0x13, 0x43, 0x04, 0x22, 0x02, 0xEA, 0x80, 0x00, 0x03, 0x43, 0x01, 0xF0, 0x03, 0x00, + 0x03, 0x43, 0xE3, 0x76, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0x90, 0xF8, 0x22, 0x00, 0x10, 0xF0, + 0x03, 0x00, 0x05, 0xD0, 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x08, 0x48, 0x70, 0x47, + 0x08, 0x48, 0x70, 0x47, 0x08, 0x48, 0x70, 0x47, 0x08, 0x48, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, + 0xCC, 0x04, 0x00, 0x22, 0x80, 0x1E, 0x00, 0x22, 0x08, 0x00, 0x00, 0x20, 0xE4, 0x07, 0x10, 0x00, + 0x00, 0x12, 0x7A, 0x00, 0x00, 0x90, 0xD0, 0x03, 0x00, 0x48, 0xE8, 0x01, 0x00, 0x24, 0xF4, 0x00, + 0xF0, 0xB5, 0x07, 0x46, 0x00, 0x20, 0x03, 0x46, 0x2F, 0x4E, 0x10, 0xE0, 0x57, 0xF8, 0x23, 0x50, + 0x03, 0x22, 0x4F, 0xEA, 0xC2, 0x0C, 0x45, 0xFA, 0x0C, 0xF4, 0x84, 0xEA, 0x20, 0x64, 0xE4, 0xB2, + 0x52, 0x1E, 0x56, 0xF8, 0x24, 0x40, 0x84, 0xEA, 0x00, 0x20, 0xF2, 0xD5, 0x5B, 0x1C, 0x8B, 0x42, + 0xEC, 0xDB, 0xF0, 0xBD, 0x30, 0xB5, 0x04, 0x46, 0x23, 0x4B, 0x00, 0x20, 0x10, 0x3B, 0x08, 0xE0, + 0x62, 0x5C, 0x02, 0xF0, 0x0F, 0x05, 0x03, 0xEB, 0x12, 0x12, 0x5D, 0x5D, 0x12, 0x78, 0x28, 0x44, + 0x10, 0x44, 0x49, 0x1E, 0xF4, 0xD2, 0x30, 0xBD, 0x10, 0xB5, 0x84, 0x68, 0x03, 0x68, 0xE4, 0x43, + 0xA3, 0x42, 0x0A, 0xD1, 0xC4, 0x68, 0x43, 0x68, 0xE4, 0x43, 0xA3, 0x42, 0x05, 0xD1, 0x5B, 0x1C, + 0x0B, 0x60, 0x00, 0x68, 0x10, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x3C, 0xB5, + 0x04, 0x46, 0x00, 0x25, 0x01, 0xAA, 0x69, 0x46, 0xFF, 0xF7, 0xE6, 0xFF, 0x01, 0x28, 0x09, 0xD1, + 0x00, 0x99, 0x04, 0xF1, 0x10, 0x00, 0x09, 0x1F, 0xFF, 0xF7, 0xB2, 0xFF, 0x01, 0x99, 0x88, 0x42, + 0x00, 0xD1, 0x01, 0x25, 0x28, 0x46, 0x3C, 0xBD, 0x30, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x09, 0x1F, + 0x10, 0x30, 0xFF, 0xF7, 0xA5, 0xFF, 0x6D, 0x1E, 0x65, 0x60, 0xE9, 0x43, 0xE1, 0x60, 0x20, 0x60, + 0xC0, 0x43, 0xA0, 0x60, 0x30, 0xBD, 0x00, 0x00, 0x1C, 0x70, 0x01, 0x00, 0x01, 0x46, 0x80, 0x00, + 0xB1, 0xF5, 0x80, 0x3F, 0x02, 0xD2, 0x10, 0x38, 0xC0, 0xF3, 0x10, 0x00, 0x70, 0x47, 0xC0, 0xF3, + 0x87, 0x20, 0x70, 0x47, 0xB0, 0xF5, 0x80, 0x2F, 0x02, 0xD2, 0x10, 0x30, 0xC0, 0xF3, 0x10, 0x00, + 0xC0, 0xF3, 0x8F, 0x00, 0x70, 0x47, 0x30, 0xB5, 0xFE, 0x4C, 0x01, 0x25, 0x25, 0x60, 0xE5, 0x06, + 0x03, 0xF0, 0x1F, 0x03, 0x85, 0xF8, 0x6B, 0x30, 0x00, 0x23, 0x04, 0xE0, 0x51, 0xF8, 0x23, 0x50, + 0x40, 0xF8, 0x23, 0x50, 0x5B, 0x1C, 0x93, 0x42, 0xF8, 0xDB, 0x00, 0x20, 0x20, 0x60, 0x30, 0xBD, + 0xF0, 0xB5, 0xF4, 0x4F, 0x01, 0x23, 0x3B, 0x60, 0x5C, 0x07, 0x84, 0xF8, 0x6B, 0x30, 0x9B, 0x1E, + 0x03, 0x60, 0x00, 0x23, 0x12, 0xE0, 0x51, 0xF8, 0x23, 0x40, 0x40, 0xF8, 0x23, 0x40, 0x00, 0x24, + 0x50, 0xF8, 0x23, 0x50, 0x51, 0xF8, 0x23, 0x60, 0xB5, 0x42, 0x06, 0xD0, 0x6D, 0x1C, 0x04, 0xD1, + 0x64, 0x1C, 0x40, 0xF8, 0x23, 0x60, 0x03, 0x2C, 0xF2, 0xD3, 0x5B, 0x1C, 0x93, 0x42, 0xEA, 0xDB, + 0x00, 0x20, 0x38, 0x60, 0xF0, 0xBD, 0xF0, 0xB5, 0x13, 0x46, 0x0A, 0x46, 0x05, 0x46, 0x00, 0x24, + 0x98, 0x18, 0x4F, 0xF4, 0x83, 0x26, 0x60, 0x28, 0x01, 0xD9, 0x01, 0x24, 0x11, 0xE0, 0x00, 0x21, + 0x07, 0xE0, 0x5F, 0x18, 0x56, 0xF8, 0x27, 0x00, 0x40, 0x1C, 0x01, 0xD0, 0x11, 0x46, 0x02, 0x24, + 0x49, 0x1C, 0x91, 0x42, 0xF5, 0xD3, 0x24, 0xB9, 0x06, 0xEB, 0x83, 0x00, 0x29, 0x46, 0xFF, 0xF7, + 0xBF, 0xFF, 0x20, 0x46, 0xF0, 0xBD, 0x10, 0xB5, 0x03, 0x46, 0x08, 0x46, 0xFF, 0xF7, 0x8E, 0xFF, + 0x01, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x92, 0x00, 0x18, 0x46, 0x01, 0xF0, 0x40, 0xBA, 0x2D, 0xE9, + 0xF0, 0x41, 0x4F, 0xF0, 0x00, 0x58, 0x0C, 0x46, 0xD8, 0xF8, 0x14, 0x70, 0x01, 0x25, 0xC0, 0xF3, + 0x8F, 0x06, 0x6F, 0xF4, 0x80, 0x41, 0xC8, 0xF8, 0x14, 0x10, 0x0E, 0x20, 0x00, 0xF0, 0x13, 0xFA, + 0x20, 0x46, 0x00, 0xF0, 0x1B, 0xFA, 0x02, 0x00, 0xC3, 0x48, 0x4F, 0xF0, 0x01, 0x01, 0x18, 0xD0, + 0x01, 0x60, 0xA4, 0xF5, 0x80, 0x34, 0x40, 0x46, 0x20, 0xF8, 0x72, 0x6F, 0x44, 0x80, 0x60, 0x22, + 0x00, 0xF8, 0x01, 0x2C, 0xBD, 0x4A, 0x11, 0x60, 0xBB, 0x4A, 0xC4, 0x32, 0x11, 0x60, 0x30, 0xBF, + 0x81, 0x79, 0x72, 0x38, 0x89, 0x07, 0x00, 0xD0, 0x00, 0x25, 0x47, 0x61, 0x28, 0x46, 0xBD, 0xE8, + 0xF0, 0x81, 0x00, 0x22, 0x02, 0x60, 0xE6, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, 0x15, 0x46, 0xDF, 0xF8, + 0xC4, 0xB2, 0x00, 0x26, 0x01, 0x27, 0x0A, 0x46, 0x04, 0x46, 0x4F, 0xF0, 0x00, 0x5C, 0xB1, 0xF5, + 0x88, 0x2F, 0x15, 0xD3, 0xA3, 0x0A, 0xFF, 0xF7, 0x41, 0xFF, 0x59, 0x46, 0xCB, 0xF8, 0x00, 0x70, + 0x03, 0xF0, 0x1F, 0x03, 0x8C, 0xF8, 0x6B, 0x30, 0x00, 0x23, 0x04, 0xE0, 0x52, 0xF8, 0x23, 0x40, + 0x40, 0xF8, 0x23, 0x40, 0x5B, 0x1C, 0xAB, 0x42, 0xF8, 0xDB, 0x0E, 0x60, 0xBD, 0xE8, 0xF0, 0x9F, + 0xDC, 0xF8, 0x14, 0x90, 0xC1, 0xF3, 0x8F, 0x08, 0xE2, 0x46, 0x6F, 0xF4, 0x80, 0x41, 0xCC, 0xF8, + 0x14, 0x10, 0x0E, 0x20, 0x00, 0xF0, 0xBF, 0xF9, 0xCB, 0xF8, 0x00, 0x70, 0x20, 0x46, 0x00, 0xF0, + 0xC5, 0xF9, 0x01, 0x00, 0x98, 0x48, 0x19, 0xD0, 0x07, 0x60, 0xA4, 0xF5, 0x80, 0x34, 0xAA, 0xF8, + 0x72, 0x80, 0xAA, 0xF8, 0x74, 0x40, 0x6D, 0x1E, 0xAA, 0xF8, 0x76, 0x50, 0x40, 0x21, 0x8A, 0xF8, + 0x71, 0x10, 0x92, 0x49, 0x0E, 0x60, 0x90, 0x49, 0xC4, 0x31, 0x0F, 0x60, 0x0A, 0xF1, 0x52, 0x00, + 0x30, 0xBF, 0xCB, 0xF8, 0x00, 0x60, 0x40, 0xF8, 0x3E, 0x9C, 0xCF, 0xE7, 0x06, 0x60, 0xE6, 0xE7, + 0x2D, 0xE9, 0xF0, 0x41, 0x4F, 0xF0, 0x00, 0x54, 0x0F, 0x46, 0x54, 0xF8, 0x14, 0x6F, 0x85, 0x08, + 0x6F, 0xF4, 0x80, 0x40, 0x20, 0x60, 0x0E, 0x20, 0x00, 0xF0, 0x8D, 0xF9, 0x00, 0x20, 0xA0, 0x66, + 0xA4, 0xF8, 0x5E, 0x50, 0x7F, 0x1E, 0xA4, 0xF8, 0x62, 0x70, 0x84, 0xF8, 0x5D, 0x00, 0x7F, 0x49, + 0x08, 0x60, 0x7D, 0x49, 0x01, 0x20, 0xC4, 0x31, 0x08, 0x60, 0x30, 0xBF, 0xE0, 0x6E, 0x26, 0x60, + 0x85, 0xE7, 0x70, 0xB5, 0x06, 0x46, 0x0C, 0x46, 0x01, 0xF1, 0x10, 0x00, 0x11, 0x1F, 0x15, 0x46, + 0x89, 0xB2, 0xFF, 0xF7, 0xD5, 0xFF, 0x20, 0x60, 0x68, 0x1E, 0x60, 0x60, 0x20, 0x68, 0x2A, 0x46, + 0xC0, 0x43, 0xA0, 0x60, 0x60, 0x68, 0x21, 0x46, 0xC0, 0x43, 0xE0, 0x60, 0x30, 0x46, 0xBD, 0xE8, + 0x70, 0x40, 0x71, 0xE7, 0xF0, 0xB5, 0x07, 0x46, 0x00, 0x20, 0x04, 0x46, 0x6C, 0x4E, 0x15, 0xE0, + 0x57, 0xF8, 0x24, 0x50, 0x03, 0x23, 0x4F, 0xEA, 0xC3, 0x0C, 0x45, 0xFA, 0x0C, 0xF2, 0x80, 0xEA, + 0x02, 0x60, 0x08, 0x22, 0x00, 0x28, 0x02, 0xDA, 0x86, 0xEA, 0x40, 0x00, 0x00, 0xE0, 0x40, 0x00, + 0x52, 0x1E, 0x00, 0x2A, 0xF6, 0xDC, 0x5B, 0x1E, 0xED, 0xD5, 0x64, 0x1C, 0x8C, 0x42, 0xE7, 0xDB, + 0xF0, 0xBD, 0x30, 0xB5, 0x50, 0xF8, 0x08, 0x4B, 0x50, 0xF8, 0x08, 0x5B, 0x30, 0xF8, 0x0C, 0x1C, + 0x49, 0x1C, 0x89, 0xB2, 0xFF, 0xF7, 0xD6, 0xFF, 0x84, 0x42, 0x04, 0xD1, 0xE0, 0x43, 0x85, 0x42, + 0x01, 0xD1, 0x01, 0x20, 0x30, 0xBD, 0x00, 0x20, 0x30, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x01, 0x26, + 0x75, 0x07, 0x04, 0x46, 0x6F, 0x69, 0x6F, 0xF4, 0x80, 0x40, 0x68, 0x61, 0x0E, 0x20, 0x00, 0xF0, + 0x22, 0xF9, 0x4F, 0xF0, 0x00, 0x08, 0xC5, 0xF8, 0x7C, 0x80, 0x20, 0x46, 0x00, 0xF0, 0x26, 0xF9, + 0x02, 0x00, 0x49, 0x49, 0x4F, 0xF0, 0x01, 0x00, 0x15, 0xD0, 0x08, 0x60, 0xA4, 0xF5, 0x80, 0x34, + 0xA5, 0xF8, 0x74, 0x40, 0x20, 0x21, 0x85, 0xF8, 0x71, 0x10, 0x44, 0x49, 0x08, 0x60, 0x42, 0x49, + 0xC4, 0x31, 0x08, 0x60, 0x30, 0xBF, 0x95, 0xF8, 0x78, 0x00, 0x80, 0x07, 0x00, 0xD0, 0x00, 0x26, + 0x6F, 0x61, 0x30, 0x46, 0x0B, 0xE7, 0xC1, 0xF8, 0x00, 0x80, 0xE9, 0xE7, 0x00, 0xB5, 0x0B, 0x46, + 0xFF, 0xF7, 0x5C, 0xFE, 0x82, 0x68, 0x01, 0x68, 0xD2, 0x43, 0x91, 0x42, 0x08, 0xD1, 0x42, 0x68, + 0xC0, 0x68, 0xC0, 0x43, 0x82, 0x42, 0x03, 0xD1, 0x52, 0x1C, 0x1A, 0x80, 0x01, 0x20, 0x00, 0xBD, + 0x00, 0x20, 0x00, 0xBD, 0xF8, 0xB5, 0x04, 0x46, 0x10, 0x30, 0x0D, 0x46, 0x06, 0x46, 0xFF, 0xF7, + 0xBE, 0xFE, 0x01, 0x28, 0x01, 0xD0, 0x00, 0x20, 0xF8, 0xBD, 0x69, 0x46, 0x28, 0x46, 0xFF, 0xF7, + 0xDD, 0xFF, 0xBD, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0x81, 0xB2, 0x30, 0x46, 0xFF, 0xF7, 0x38, 0xFF, + 0x20, 0x60, 0xBD, 0xF8, 0x00, 0x10, 0xC0, 0x43, 0x49, 0x1E, 0x61, 0x60, 0xA0, 0x60, 0xC8, 0x43, + 0xE0, 0x60, 0x01, 0x20, 0xF8, 0xBD, 0xF0, 0xB5, 0xB1, 0xB0, 0x07, 0x46, 0x6D, 0x46, 0x21, 0x4E, + 0x01, 0x24, 0xC0, 0x21, 0x28, 0x46, 0x01, 0xF0, 0x36, 0xF9, 0x00, 0x20, 0x56, 0xF8, 0x20, 0x10, + 0x45, 0xF8, 0x20, 0x10, 0x40, 0x1C, 0x30, 0x28, 0xF8, 0xD3, 0x1B, 0x49, 0x00, 0x98, 0x88, 0x42, + 0x10, 0xD1, 0x02, 0x98, 0x81, 0xB2, 0x05, 0xA8, 0x04, 0x46, 0xFF, 0xF7, 0x4B, 0xFF, 0x01, 0x99, + 0x81, 0x42, 0x06, 0xD1, 0xAC, 0x22, 0x21, 0x46, 0x38, 0x46, 0x01, 0xF0, 0xC0, 0xF8, 0x00, 0x24, + 0x00, 0xE0, 0x03, 0x24, 0x31, 0xB0, 0x20, 0x46, 0xF0, 0xBD, 0x70, 0xB5, 0x94, 0xB0, 0x04, 0x46, + 0x6D, 0x46, 0x0E, 0x4E, 0x50, 0x21, 0x28, 0x46, 0x01, 0xF0, 0x0D, 0xF9, 0x00, 0x20, 0x56, 0xF8, + 0x20, 0x10, 0x45, 0xF8, 0x20, 0x10, 0x40, 0x1C, 0x14, 0x28, 0xF8, 0xD3, 0x08, 0x48, 0x6F, 0xF0, + 0x02, 0x05, 0x0F, 0xE0, 0xC4, 0x1B, 0x00, 0x22, 0x78, 0x0D, 0x00, 0x22, 0x1C, 0x0F, 0x00, 0x22, + 0x1B, 0x00, 0x00, 0x80, 0x48, 0x1D, 0x04, 0x00, 0xB2, 0x57, 0x0E, 0x70, 0xAC, 0x1E, 0x04, 0x00, + 0x5C, 0x00, 0x0D, 0x60, 0x00, 0x99, 0x81, 0x42, 0x2E, 0xD1, 0xA8, 0x10, 0x20, 0x60, 0x60, 0x60, + 0xA0, 0x60, 0xE0, 0x60, 0x20, 0x61, 0x02, 0x98, 0x81, 0xB2, 0x05, 0xA8, 0xFF, 0xF7, 0x0A, 0xFF, + 0x01, 0x99, 0x81, 0x42, 0x20, 0xD1, 0xBD, 0xF8, 0x38, 0x10, 0x45, 0xF2, 0xAA, 0x50, 0x81, 0x42, + 0x0C, 0xD1, 0x9D, 0xF8, 0x1D, 0x10, 0x21, 0x60, 0x9D, 0xF8, 0x1C, 0x10, 0x01, 0xF0, 0x0F, 0x01, + 0x61, 0x60, 0x9D, 0xF8, 0x1E, 0x10, 0x01, 0xF0, 0x0F, 0x01, 0xA1, 0x60, 0xBD, 0xF8, 0x3C, 0x10, + 0x81, 0x42, 0x01, 0xD1, 0x08, 0x99, 0xE1, 0x60, 0xBD, 0xF8, 0x40, 0x10, 0x81, 0x42, 0x01, 0xD1, + 0x09, 0x98, 0x20, 0x61, 0x14, 0xB0, 0x70, 0xBD, 0x25, 0x60, 0x65, 0x60, 0xA5, 0x60, 0xE5, 0x60, + 0x25, 0x61, 0xF7, 0xE7, 0x70, 0xB5, 0x86, 0xB0, 0x04, 0x46, 0x6D, 0x46, 0x27, 0x4E, 0x14, 0x21, + 0x28, 0x46, 0x01, 0xF0, 0xB0, 0xF8, 0x00, 0x21, 0x56, 0xF8, 0x21, 0x00, 0x45, 0xF8, 0x21, 0x00, + 0x49, 0x1C, 0x05, 0x29, 0xF8, 0xD3, 0x00, 0x98, 0x20, 0x60, 0x01, 0x98, 0x60, 0x60, 0x02, 0x98, + 0xC0, 0xB2, 0xA0, 0x60, 0x03, 0x98, 0xC0, 0xB2, 0xE0, 0x60, 0x04, 0x98, 0xC0, 0xB2, 0x20, 0x61, + 0x06, 0xB0, 0x70, 0xBD, 0x1C, 0xB5, 0x00, 0x20, 0x18, 0x4A, 0x00, 0x90, 0x84, 0x3A, 0x6B, 0x46, + 0x01, 0x46, 0x01, 0x90, 0x52, 0xF8, 0x21, 0x40, 0x43, 0xF8, 0x21, 0x40, 0x49, 0x1C, 0x02, 0x29, + 0xF8, 0xD3, 0xBD, 0xF8, 0x00, 0x10, 0xA1, 0xF5, 0xAA, 0x42, 0xAA, 0x3A, 0x0A, 0xD1, 0xBD, 0xF8, + 0x04, 0x20, 0x11, 0x42, 0x06, 0xD1, 0x9D, 0xF8, 0x02, 0x10, 0x9D, 0xF8, 0x06, 0x20, 0x11, 0x42, + 0x00, 0xD1, 0x08, 0x46, 0x1C, 0xBD, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, + 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0xB0, 0xF5, 0x80, 0x3F, + 0x01, 0xD2, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0x60, 0x1F, 0x04, 0x00, + 0x4F, 0xF0, 0x00, 0x50, 0x00, 0x21, 0x80, 0xF8, 0x3D, 0x10, 0x80, 0xF8, 0x3E, 0x10, 0x80, 0xF8, + 0x3F, 0x10, 0x3F, 0x22, 0x80, 0xF8, 0x32, 0x20, 0x00, 0xF8, 0x30, 0x1F, 0x02, 0x71, 0x41, 0x71, + 0x42, 0x70, 0x01, 0x72, 0x41, 0x72, 0x81, 0x72, 0xC1, 0x72, 0xC1, 0x71, 0x70, 0x47, 0x99, 0x4A, + 0x10, 0x60, 0x98, 0x48, 0x0C, 0x30, 0x01, 0x60, 0x70, 0x47, 0x30, 0xB5, 0x01, 0x24, 0x84, 0x40, + 0xE0, 0xB2, 0x4F, 0xF0, 0x00, 0x54, 0x00, 0x29, 0x03, 0x9D, 0x94, 0xF8, 0x32, 0x10, 0x01, 0xD0, + 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x84, 0xF8, 0x32, 0x10, 0x94, 0xF8, 0x30, 0x10, 0x0A, 0xB1, + 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x84, 0xF8, 0x30, 0x10, 0x94, 0xF8, 0x34, 0x10, 0x0B, 0xB1, + 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x84, 0xF8, 0x34, 0x10, 0x14, 0xF8, 0x35, 0x1F, 0x0D, 0xB1, + 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x21, 0x70, 0x30, 0xBD, 0x4F, 0xF0, 0x00, 0x52, 0x06, 0x28, + 0x17, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x06, 0x09, 0x0F, 0x17, 0x1A, 0x12, 0xF8, 0x3D, 0x0F, + 0x04, 0xE0, 0x12, 0xF8, 0x3D, 0x0F, 0x07, 0xE0, 0x12, 0xF8, 0x3E, 0x0F, 0x20, 0xF0, 0x0F, 0x00, + 0x08, 0x43, 0x05, 0xE0, 0x12, 0xF8, 0x3E, 0x0F, 0x20, 0xF0, 0xF0, 0x00, 0x40, 0xEA, 0x01, 0x10, + 0x10, 0x70, 0x70, 0x47, 0x12, 0xF8, 0x3F, 0x0F, 0xF0, 0xE7, 0x12, 0xF8, 0x3F, 0x0F, 0xF3, 0xE7, + 0x01, 0x23, 0x83, 0x40, 0xD8, 0xB2, 0x4F, 0xF0, 0x00, 0x53, 0x00, 0x29, 0x93, 0xF8, 0x38, 0x10, + 0x01, 0xD0, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x83, 0xF8, 0x38, 0x10, 0x13, 0xF8, 0x39, 0x1F, + 0x0A, 0xB1, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x19, 0x70, 0x70, 0x47, 0x01, 0x23, 0x83, 0x40, + 0xD8, 0xB2, 0x4F, 0xF0, 0x00, 0x53, 0x00, 0x29, 0x93, 0xF8, 0x3A, 0x10, 0x01, 0xD0, 0x01, 0x43, + 0x00, 0xE0, 0x81, 0x43, 0x83, 0xF8, 0x3A, 0x10, 0x13, 0xF8, 0x3A, 0x1F, 0x0A, 0xB1, 0x01, 0x43, + 0x00, 0xE0, 0x81, 0x43, 0x19, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x01, 0x20, + 0xA8, 0x40, 0xC4, 0xB2, 0x1E, 0x46, 0x90, 0x46, 0x0F, 0x46, 0x0A, 0x20, 0x00, 0xF0, 0x93, 0xF8, + 0x0B, 0x20, 0x00, 0xF0, 0x90, 0xF8, 0x0A, 0x20, 0x00, 0xF0, 0x98, 0xF8, 0x0B, 0x20, 0x00, 0xF0, + 0x95, 0xF8, 0x4F, 0xF0, 0x00, 0x50, 0x8F, 0xB1, 0x90, 0xF8, 0x2E, 0x10, 0xA1, 0x43, 0x80, 0xF8, + 0x2E, 0x10, 0x90, 0xF8, 0x38, 0x10, 0x21, 0x43, 0x80, 0xF8, 0x38, 0x10, 0x90, 0xF8, 0x3A, 0x10, + 0x21, 0x43, 0x80, 0xF8, 0x3A, 0x10, 0x48, 0x49, 0x41, 0xF8, 0x25, 0x60, 0xB8, 0xF1, 0x00, 0x0F, + 0x0D, 0xD0, 0x10, 0xF8, 0x2F, 0x1F, 0xA1, 0x43, 0x01, 0x70, 0x81, 0x7A, 0x21, 0x43, 0x81, 0x72, + 0x01, 0x7B, 0x21, 0x43, 0x01, 0x73, 0x40, 0x48, 0x20, 0x30, 0x40, 0xF8, 0x25, 0x60, 0x0A, 0x20, + 0x00, 0xF0, 0x56, 0xF8, 0xBD, 0xE8, 0xF0, 0x41, 0x0B, 0x20, 0x00, 0xF0, 0x51, 0xB8, 0x2D, 0xE9, + 0xF0, 0x41, 0x05, 0x46, 0x01, 0x20, 0xA8, 0x40, 0xC4, 0xB2, 0x17, 0x46, 0x0E, 0x46, 0x0A, 0x20, + 0x00, 0xF0, 0x51, 0xF8, 0x0B, 0x20, 0x00, 0xF0, 0x4E, 0xF8, 0x0A, 0x20, 0x00, 0xF0, 0x56, 0xF8, + 0x0B, 0x20, 0x00, 0xF0, 0x53, 0xF8, 0x31, 0x00, 0x4F, 0xF0, 0x00, 0x02, 0x4F, 0xF0, 0x00, 0x56, + 0x11, 0xD0, 0x96, 0xF8, 0x38, 0x00, 0xA0, 0x43, 0x86, 0xF8, 0x38, 0x00, 0x96, 0xF8, 0x2E, 0x00, + 0xA0, 0x43, 0x86, 0xF8, 0x2E, 0x00, 0x96, 0xF8, 0x3A, 0x00, 0xA0, 0x43, 0x86, 0xF8, 0x3A, 0x00, + 0x25, 0x48, 0x40, 0xF8, 0x25, 0x20, 0x97, 0xB1, 0x96, 0xF8, 0x39, 0x00, 0xA0, 0x43, 0x86, 0xF8, + 0x39, 0x00, 0x96, 0xF8, 0x2F, 0x00, 0xA0, 0x43, 0x86, 0xF8, 0x2F, 0x00, 0x96, 0xF8, 0x3B, 0x00, + 0xA0, 0x43, 0x86, 0xF8, 0x3B, 0x00, 0x1C, 0x48, 0x20, 0x30, 0x40, 0xF8, 0x25, 0x20, 0x96, 0xF8, + 0x38, 0x00, 0x10, 0xB1, 0x0A, 0x20, 0x00, 0xF0, 0x0B, 0xF8, 0x96, 0xF8, 0x39, 0x00, 0x00, 0x28, + 0x04, 0xD0, 0xBD, 0xE8, 0xF0, 0x41, 0x0B, 0x20, 0x00, 0xF0, 0x02, 0xB8, 0xBD, 0xE8, 0xF0, 0x81, + 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, + 0xC0, 0xF8, 0x00, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, + 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, + 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, + 0x70, 0x47, 0x00, 0x00, 0x38, 0x05, 0x00, 0x22, 0xFC, 0x87, 0x10, 0x00, 0xF0, 0xB5, 0x63, 0x4D, + 0xD0, 0xE9, 0x00, 0x23, 0x01, 0x21, 0xEC, 0x1D, 0xFF, 0x27, 0x4E, 0x07, 0x00, 0x7A, 0x86, 0xF8, + 0xE5, 0x70, 0x86, 0xF8, 0xE4, 0x70, 0x00, 0x27, 0xC6, 0xF8, 0xC0, 0x70, 0xC6, 0xF8, 0xE8, 0x70, + 0x86, 0xF8, 0xE1, 0x70, 0x86, 0xF8, 0xE3, 0x70, 0x8E, 0x46, 0x58, 0xE0, 0x17, 0x78, 0x05, 0xF8, + 0x01, 0x7B, 0x1F, 0x88, 0x24, 0xF8, 0x02, 0x7B, 0xD7, 0x78, 0x01, 0x2F, 0x02, 0xD0, 0x02, 0x2F, + 0x09, 0xD0, 0x10, 0xE0, 0x96, 0xF8, 0xE4, 0x70, 0x0E, 0xFA, 0x01, 0xFC, 0x27, 0xEA, 0x0C, 0x07, + 0x86, 0xF8, 0xE4, 0x70, 0x07, 0xE0, 0x96, 0xF8, 0xE5, 0x70, 0x0E, 0xFA, 0x01, 0xFC, 0x27, 0xEA, + 0x0C, 0x07, 0x86, 0xF8, 0xE5, 0x70, 0x4F, 0x1E, 0x07, 0xEB, 0x47, 0x0C, 0x27, 0xF0, 0x01, 0x07, + 0xBC, 0x44, 0x57, 0x78, 0x07, 0xF0, 0x07, 0x07, 0x07, 0xFA, 0x0C, 0xF7, 0xD6, 0xF8, 0xC0, 0xC0, + 0x47, 0xEA, 0x0C, 0x07, 0xC6, 0xF8, 0xC0, 0x70, 0x97, 0x78, 0x4F, 0xEA, 0x81, 0x0C, 0x07, 0xF0, + 0x0F, 0x07, 0xAC, 0xF1, 0x04, 0x0C, 0x07, 0xFA, 0x0C, 0xF7, 0xD6, 0xF8, 0xE8, 0xC0, 0x47, 0xEA, + 0x0C, 0x07, 0xC6, 0xF8, 0xE8, 0x70, 0x17, 0x79, 0xFF, 0x07, 0x07, 0xD0, 0x96, 0xF8, 0xE1, 0x70, + 0x0E, 0xFA, 0x01, 0xFC, 0x47, 0xEA, 0x0C, 0x07, 0x86, 0xF8, 0xE1, 0x70, 0x17, 0x79, 0xFF, 0x06, + 0x07, 0xD5, 0x96, 0xF8, 0xE3, 0x70, 0x0E, 0xFA, 0x01, 0xFC, 0x47, 0xEA, 0x0C, 0x07, 0x86, 0xF8, + 0xE3, 0x70, 0x49, 0x1C, 0x08, 0x29, 0x04, 0xD2, 0x40, 0x1E, 0x52, 0x1D, 0x9B, 0x1C, 0x00, 0x28, + 0xA4, 0xD1, 0xD6, 0xF8, 0xE8, 0x00, 0x70, 0x64, 0xF0, 0xBD, 0xF0, 0xB5, 0x27, 0x4D, 0x28, 0x4F, + 0x01, 0x26, 0xEC, 0x1D, 0xC2, 0x79, 0x00, 0x21, 0x03, 0x68, 0x79, 0x60, 0x27, 0x07, 0x4F, 0xF0, + 0xFF, 0x0E, 0x87, 0xF8, 0xE5, 0xE0, 0x87, 0xF8, 0xE4, 0x60, 0xC7, 0xF8, 0xC0, 0x10, 0x87, 0xF8, + 0xE1, 0x10, 0x87, 0xF8, 0xE3, 0x10, 0x18, 0xE0, 0x93, 0xF8, 0x00, 0xC0, 0x05, 0xF8, 0x01, 0xCB, + 0xB0, 0xF8, 0x04, 0xC0, 0x24, 0xF8, 0x02, 0xCB, 0x90, 0xF8, 0x06, 0xC0, 0x4F, 0xEA, 0x86, 0x0E, + 0x0C, 0xF0, 0x0F, 0x0C, 0xAE, 0xF1, 0x04, 0x0E, 0x0C, 0xFA, 0x0E, 0xFC, 0x76, 0x1C, 0x4C, 0xEA, + 0x01, 0x01, 0x08, 0x2E, 0x03, 0xD2, 0x52, 0x1E, 0x5B, 0x1C, 0x00, 0x2A, 0xE4, 0xD1, 0xC7, 0xF8, + 0xE8, 0x10, 0x79, 0x64, 0xF0, 0xBD, 0x0D, 0x4A, 0xD2, 0x1D, 0x22, 0xF8, 0x10, 0x10, 0x70, 0x47, + 0x10, 0xB5, 0x04, 0x46, 0x0B, 0x48, 0x00, 0x68, 0x38, 0xB1, 0xA0, 0x68, 0xFF, 0xF7, 0x46, 0xFF, + 0x20, 0x68, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x0F, 0xB8, 0xE0, 0x68, 0xFF, 0xF7, 0x3E, 0xFF, + 0x60, 0x68, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xCB, 0xBC, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x22, 0xBC, 0x05, 0x00, 0x22, 0x10, 0xB5, 0x4F, 0x4B, 0x01, 0x68, 0x00, 0x24, + 0x99, 0x60, 0x81, 0x88, 0x59, 0x80, 0x02, 0x89, 0x9A, 0x80, 0x1C, 0x70, 0x4F, 0xF0, 0x00, 0x53, + 0xA3, 0xF8, 0x1A, 0x21, 0xA3, 0xF8, 0x1E, 0x11, 0xC0, 0x88, 0xA3, 0xF8, 0x20, 0x01, 0x47, 0x48, + 0x01, 0x22, 0xC0, 0xF8, 0xD8, 0x21, 0xC0, 0xF8, 0xDC, 0x21, 0xC0, 0xF8, 0xC4, 0x21, 0xC0, 0xF8, + 0xCC, 0x21, 0xC0, 0xF8, 0xD4, 0x21, 0xC0, 0xF8, 0x80, 0x21, 0x72, 0xB6, 0xD0, 0xF8, 0x08, 0x12, + 0x00, 0x29, 0xFB, 0xD1, 0x42, 0x60, 0x62, 0xB6, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x3B, 0x4D, + 0xD5, 0xF8, 0x5C, 0x01, 0x38, 0x4F, 0x2E, 0x04, 0x01, 0x24, 0xBA, 0x68, 0x50, 0xB3, 0xB6, 0xF8, + 0x1C, 0x81, 0x5F, 0xEA, 0x08, 0x00, 0x0F, 0xD0, 0xD5, 0xF8, 0x54, 0x01, 0x10, 0xB9, 0xD5, 0xF8, + 0x00, 0x01, 0x48, 0xB1, 0x41, 0x46, 0x01, 0x20, 0x90, 0x47, 0xC5, 0xF8, 0xD8, 0x42, 0xD5, 0xF8, + 0x54, 0x01, 0x08, 0xB1, 0xC5, 0xF8, 0xD4, 0x42, 0xBA, 0x68, 0x41, 0x46, 0x02, 0x20, 0x90, 0x47, + 0x01, 0x78, 0x02, 0x29, 0x02, 0xD0, 0x03, 0x29, 0x02, 0xD0, 0x08, 0xE0, 0x41, 0x88, 0x00, 0xE0, + 0x79, 0x88, 0xA6, 0xF8, 0x1E, 0x11, 0x80, 0x88, 0xA6, 0xF8, 0x1A, 0x01, 0x3C, 0x70, 0xC5, 0xF8, + 0xDC, 0x42, 0x38, 0xE0, 0xD5, 0xF8, 0x44, 0x01, 0x80, 0xB1, 0xB6, 0xF8, 0x1C, 0x11, 0x03, 0x20, + 0x90, 0x47, 0x38, 0x78, 0x38, 0xB1, 0x78, 0x88, 0xA6, 0xF8, 0x1E, 0x01, 0xB8, 0x88, 0xA6, 0xF8, + 0x1A, 0x01, 0x00, 0x20, 0x38, 0x70, 0xC5, 0xF8, 0xC4, 0x42, 0x24, 0xE0, 0xD5, 0xF8, 0x58, 0x01, + 0x30, 0xB1, 0xB6, 0xF8, 0x1C, 0x11, 0x01, 0x20, 0x90, 0x47, 0xC5, 0xF8, 0xD8, 0x42, 0x1A, 0xE0, + 0xD5, 0xF8, 0x4C, 0x01, 0x28, 0xB9, 0xD5, 0xF8, 0x54, 0x01, 0x10, 0xB9, 0xD5, 0xF8, 0x00, 0x01, + 0x88, 0xB1, 0xB6, 0xF8, 0x1C, 0x11, 0x19, 0xB1, 0x01, 0x20, 0x90, 0x47, 0xC5, 0xF8, 0xD8, 0x42, + 0xD5, 0xF8, 0x4C, 0x01, 0x10, 0xB1, 0xC5, 0xF8, 0xCC, 0x42, 0x04, 0xE0, 0xD5, 0xF8, 0x54, 0x01, + 0x08, 0xB1, 0xC5, 0xF8, 0xD4, 0x42, 0xD5, 0xF8, 0x00, 0x01, 0x00, 0x28, 0x01, 0xD0, 0xC5, 0xF8, + 0x80, 0x42, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, 0xE8, 0x07, 0x10, 0x00, 0x00, 0x20, 0x00, 0x22, + 0xF6, 0x49, 0x00, 0x20, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, + 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, + 0x08, 0x60, 0xEF, 0x49, 0x01, 0x22, 0x0A, 0x60, 0xED, 0x49, 0x14, 0x31, 0x08, 0x60, 0x51, 0x07, + 0x01, 0xF8, 0x50, 0x0F, 0xFF, 0x23, 0x4B, 0x70, 0x01, 0xF8, 0x05, 0x0C, 0x10, 0x23, 0x4B, 0x80, + 0x8A, 0x80, 0xE8, 0x49, 0x08, 0x60, 0x48, 0x60, 0x88, 0x60, 0xC8, 0x60, 0x08, 0x61, 0x48, 0x61, + 0x88, 0x61, 0xC8, 0x61, 0x08, 0x62, 0x70, 0x47, 0x70, 0x47, 0xE2, 0x4A, 0x11, 0x60, 0xDF, 0x49, + 0x00, 0x22, 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, + 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8, 0x58, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0xD9, 0x4B, + 0x10, 0xB5, 0xD6, 0x4A, 0x19, 0x60, 0x00, 0x21, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, + 0x51, 0x40, 0xE4, 0x07, 0x07, 0xD0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x58, 0x00, + 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, + 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, 0xF1, 0xE7, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x58, 0x00, + 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x50, 0x90, 0xF8, 0x22, 0x00, 0xC0, 0xF3, 0x81, 0x00, 0x28, 0xB1, + 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xC3, 0x48, 0x70, 0x47, 0xC3, 0x48, 0x70, 0x47, + 0xC3, 0x48, 0x70, 0x47, 0xC3, 0x48, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, + 0x51, 0x00, 0xBA, 0x49, 0xC2, 0x07, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0xD0, 0x08, 0x60, 0x70, 0xBD, + 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x04, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8, + 0x58, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x58, 0x00, 0xFF, 0xF7, 0x75, 0xF9, 0x01, 0x46, 0xFF, 0xF7, + 0xD0, 0xFF, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0x63, 0xFA, 0x65, 0x61, 0x02, 0x20, 0x00, 0xF0, + 0x35, 0xFB, 0x62, 0xB6, 0x70, 0xBD, 0xAB, 0x48, 0x10, 0xB5, 0x00, 0x21, 0x04, 0x68, 0x01, 0x60, + 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x00, 0x20, + 0xFF, 0xF7, 0x82, 0xFF, 0x10, 0xBD, 0xA3, 0x4A, 0x51, 0x60, 0xA0, 0x49, 0x00, 0x22, 0x09, 0x1D, + 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0xCA, 0x06, + 0xA2, 0xF8, 0x5A, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x9A, 0x4B, 0x10, 0xB5, 0x59, 0x60, + 0x96, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0xD1, 0x06, 0x91, 0xF8, 0x51, 0x40, 0xA4, 0x07, + 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, + 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x5A, 0x00, 0x01, 0x20, + 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x5A, 0x00, 0x70, 0x47, 0x70, 0xB5, + 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x8B, 0x49, 0x82, 0x07, 0x4F, 0xF0, 0x00, 0x00, + 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x08, 0x02, 0x62, 0x61, 0x08, 0x60, + 0xB4, 0xF8, 0x5A, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x5A, 0x00, 0xFF, 0xF7, 0x0C, 0xF9, 0x01, 0x46, + 0xFF, 0xF7, 0x67, 0xFF, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0xFA, 0xF9, 0x65, 0x61, 0x03, 0x20, + 0x00, 0xF0, 0xCC, 0xFA, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0x75, 0x48, 0x10, 0xB5, + 0x00, 0x21, 0x44, 0x68, 0x41, 0x60, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, + 0x10, 0x40, 0x60, 0x47, 0x01, 0x20, 0xFF, 0xF7, 0x17, 0xFF, 0x10, 0xBD, 0x6D, 0x4A, 0x91, 0x60, + 0x71, 0x49, 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, + 0x02, 0xEA, 0x40, 0x00, 0x8A, 0x06, 0xA2, 0xF8, 0x5C, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, + 0x64, 0x4B, 0x10, 0xB5, 0x99, 0x60, 0x68, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x91, 0x06, + 0x91, 0xF8, 0x51, 0x40, 0x64, 0x07, 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, + 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, + 0xA1, 0xF8, 0x5C, 0x00, 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, + 0x5C, 0x00, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x57, 0x49, + 0x42, 0x07, 0x4F, 0xF0, 0x00, 0x00, 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, + 0x10, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8, 0x5C, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x5C, 0x00, + 0xFF, 0xF7, 0xA1, 0xF8, 0x01, 0x46, 0xFF, 0xF7, 0xFC, 0xFE, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, + 0x8F, 0xF9, 0x65, 0x61, 0x04, 0x20, 0x00, 0xF0, 0x61, 0xFA, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, + 0x70, 0xBD, 0x40, 0x48, 0x10, 0xB5, 0x00, 0x21, 0x84, 0x68, 0x81, 0x60, 0xFF, 0xF7, 0xD2, 0xFF, + 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x02, 0x20, 0xFF, 0xF7, 0xAC, 0xFE, + 0x10, 0xBD, 0x38, 0x4A, 0xD1, 0x60, 0x3D, 0x49, 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, 0x00, 0xEB, + 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8, + 0x5E, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x2E, 0x4B, 0x10, 0xB5, 0xD9, 0x60, 0x33, 0x4A, + 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, 0x24, 0x07, + 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, + 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x5E, 0x00, 0x01, 0x20, + 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x5E, 0x00, 0x70, 0x47, 0x70, 0xB5, + 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x21, 0x49, 0x02, 0x07, 0x4F, 0xF0, 0x00, 0x00, + 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x20, 0x02, 0x62, 0x61, 0x08, 0x60, + 0xB4, 0xF8, 0x5E, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x5E, 0x00, 0xFF, 0xF7, 0x34, 0xF8, 0x01, 0x46, + 0xFF, 0xF7, 0x8F, 0xFE, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0x22, 0xF9, 0x65, 0x61, 0x05, 0x20, + 0x00, 0xF0, 0xF4, 0xF9, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0x09, 0x48, 0x10, 0xB5, + 0x00, 0x21, 0xC4, 0x68, 0xC1, 0x60, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, + 0x10, 0x40, 0x60, 0x47, 0x03, 0x20, 0xFF, 0xF7, 0x3F, 0xFE, 0x10, 0xBD, 0x40, 0x09, 0x00, 0x22, + 0xC0, 0x04, 0x00, 0x22, 0xF4, 0x07, 0x10, 0x00, 0x00, 0x09, 0x3D, 0x00, 0x00, 0x48, 0xE8, 0x01, + 0x00, 0x24, 0xF4, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x44, 0x09, 0x00, 0x22, 0x48, 0x09, 0x00, 0x22, + 0x4C, 0x09, 0x00, 0x22, 0xEB, 0x4A, 0x11, 0x61, 0xEB, 0x49, 0x00, 0x22, 0x0A, 0x60, 0x00, 0xEB, + 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8, + 0x60, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0xE2, 0x4B, 0x10, 0xB5, 0xE2, 0x4A, 0x19, 0x61, + 0x00, 0x21, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, 0xE4, 0x06, 0x08, 0xD4, + 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, + 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x60, 0x00, 0x01, 0x20, 0x10, 0x60, + 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x60, 0x00, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, + 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0xD0, 0x49, 0xC2, 0x06, 0x4F, 0xF0, 0x00, 0x00, 0x1A, 0xD4, + 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x40, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8, + 0x60, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x60, 0x00, 0xFE, 0xF7, 0xB5, 0xFF, 0x01, 0x46, 0xFF, 0xF7, + 0x10, 0xFE, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0xA3, 0xF8, 0x65, 0x61, 0x06, 0x20, 0x00, 0xF0, + 0x75, 0xF9, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0xBE, 0x48, 0x10, 0xB5, 0x00, 0x21, + 0x04, 0x69, 0x01, 0x61, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, + 0x60, 0x47, 0x04, 0x20, 0xFF, 0xF7, 0xC0, 0xFD, 0x10, 0xBD, 0xB6, 0x4A, 0x51, 0x61, 0xB6, 0x49, + 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, + 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8, 0x62, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, + 0xAC, 0x4B, 0x10, 0xB5, 0x59, 0x61, 0xAC, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x4F, 0xF0, + 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, 0xA4, 0x06, 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, + 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, + 0x80, 0x09, 0xA1, 0xF8, 0x62, 0x00, 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, + 0xB0, 0xF8, 0x62, 0x00, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, + 0x9A, 0x49, 0x82, 0x06, 0x4F, 0xF0, 0x00, 0x00, 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, + 0x42, 0xF0, 0x80, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8, 0x62, 0x10, 0x09, 0xB1, 0xA4, 0xF8, + 0x62, 0x00, 0xFE, 0xF7, 0x48, 0xFF, 0x01, 0x46, 0xFF, 0xF7, 0xA3, 0xFD, 0xB1, 0xFB, 0xF0, 0xF0, + 0xEA, 0xF7, 0x36, 0xF8, 0x65, 0x61, 0x07, 0x20, 0x00, 0xF0, 0x08, 0xF9, 0x62, 0xB6, 0x70, 0xBD, + 0x08, 0x60, 0x70, 0xBD, 0x87, 0x48, 0x10, 0xB5, 0x00, 0x21, 0x44, 0x69, 0x41, 0x61, 0xFF, 0xF7, + 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x05, 0x20, 0xFF, 0xF7, + 0x53, 0xFD, 0x10, 0xBD, 0x7F, 0x4A, 0x91, 0x61, 0x80, 0x49, 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, + 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, + 0xA2, 0xF8, 0x64, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x76, 0x4B, 0x10, 0xB5, 0x99, 0x61, + 0x76, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, + 0x64, 0x06, 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, + 0x03, 0xEA, 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x64, 0x00, + 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x64, 0x00, 0x70, 0x47, + 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x65, 0x49, 0x42, 0x06, 0x4F, 0xF0, + 0x00, 0x00, 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF4, 0x80, 0x72, 0x62, 0x61, + 0x08, 0x60, 0xB4, 0xF8, 0x64, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x64, 0x00, 0xFE, 0xF7, 0xDB, 0xFE, + 0x01, 0x46, 0xFF, 0xF7, 0x36, 0xFD, 0xB1, 0xFB, 0xF0, 0xF0, 0xE9, 0xF7, 0xC9, 0xFF, 0x65, 0x61, + 0x08, 0x20, 0x00, 0xF0, 0x9B, 0xF8, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0x51, 0x48, + 0x10, 0xB5, 0x00, 0x21, 0x84, 0x69, 0x81, 0x61, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, + 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x06, 0x20, 0xFF, 0xF7, 0xE6, 0xFC, 0x10, 0xBD, 0x10, 0xB5, + 0xFE, 0xF7, 0xA0, 0xFE, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x22, 0x20, 0x42, 0xF2, 0x10, 0x73, + 0xB0, 0xFB, 0xF3, 0xF0, 0xC2, 0xF3, 0x81, 0x02, 0x52, 0x1C, 0xD0, 0x40, 0xB1, 0xF8, 0x54, 0x20, + 0xC9, 0x6C, 0x51, 0x43, 0x89, 0x09, 0xB0, 0xFB, 0xF1, 0xF0, 0x10, 0xBD, 0x40, 0x49, 0x00, 0x22, + 0x09, 0x1D, 0x0A, 0x60, 0x3B, 0x4A, 0x12, 0x6A, 0x50, 0x43, 0x4F, 0xF0, 0x00, 0x52, 0x80, 0x09, + 0xA2, 0xF8, 0x66, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x39, 0x49, 0x00, 0x20, 0x09, 0x1D, + 0x08, 0x60, 0x70, 0x47, 0x33, 0x49, 0xC8, 0x61, 0x35, 0x49, 0x01, 0x20, 0xA0, 0x31, 0x08, 0x60, + 0x09, 0x1D, 0x08, 0x60, 0x70, 0x47, 0x2F, 0x4A, 0x10, 0xB5, 0x00, 0x20, 0xD1, 0x69, 0xD0, 0x61, + 0x51, 0xB1, 0x2F, 0x4A, 0xA0, 0x32, 0x10, 0x60, 0x4F, 0xF0, 0x00, 0x50, 0xC0, 0x6C, 0xBD, 0xE8, + 0x10, 0x40, 0x20, 0xF0, 0x7F, 0x40, 0x08, 0x47, 0xFF, 0x20, 0xFF, 0xF7, 0x9D, 0xFC, 0x10, 0xBD, + 0x10, 0xB5, 0x04, 0x46, 0xFE, 0xF7, 0x56, 0xFE, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x22, 0x10, + 0x42, 0xF2, 0x10, 0x72, 0xB0, 0xFB, 0xF2, 0xF0, 0xC1, 0xF3, 0x81, 0x01, 0x49, 0x1C, 0xC8, 0x40, + 0x00, 0x03, 0xB0, 0xFB, 0xF4, 0xF0, 0x1B, 0x49, 0x08, 0x62, 0x10, 0xBD, 0x30, 0xB5, 0x4F, 0xF0, + 0x00, 0x55, 0x01, 0x24, 0x84, 0x40, 0x95, 0xF8, 0x51, 0x00, 0x09, 0xB1, 0x20, 0x43, 0x00, 0xE0, + 0xA0, 0x43, 0x85, 0xF8, 0x51, 0x00, 0x95, 0xF8, 0x4B, 0x00, 0x0A, 0xB1, 0x20, 0x43, 0x00, 0xE0, + 0xA0, 0x43, 0x85, 0xF8, 0x4B, 0x00, 0x15, 0xF8, 0x50, 0x0F, 0x0B, 0xB1, 0x20, 0x43, 0x00, 0xE0, + 0xA0, 0x43, 0x28, 0x70, 0x30, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0xF8, 0x4A, 0x1F, 0xC0, 0x79, + 0x81, 0x43, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, + 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, + 0x70, 0x47, 0x00, 0x00, 0xF4, 0x07, 0x10, 0x00, 0x50, 0x09, 0x00, 0x22, 0x54, 0x09, 0x00, 0x22, + 0x58, 0x09, 0x00, 0x22, 0x00, 0x21, 0x01, 0x60, 0x08, 0x46, 0x70, 0x47, 0x30, 0xB5, 0x0A, 0x68, + 0x12, 0xB1, 0x0B, 0x46, 0x84, 0x6A, 0x08, 0xE0, 0x00, 0x22, 0x08, 0x60, 0xC0, 0xE9, 0x03, 0x21, + 0x0A, 0xE0, 0x02, 0xF1, 0x0C, 0x03, 0xD2, 0x68, 0x12, 0xB1, 0x95, 0x6A, 0xA5, 0x42, 0xF8, 0xDC, + 0x1A, 0x68, 0xC0, 0xE9, 0x03, 0x21, 0x18, 0x60, 0x00, 0x20, 0x30, 0xBD, 0x00, 0x68, 0x00, 0x22, + 0x01, 0xE0, 0xC0, 0x68, 0x52, 0x1C, 0x8A, 0x42, 0x01, 0xD0, 0x00, 0x28, 0xF9, 0xD1, 0x70, 0x47, + 0x00, 0x68, 0x70, 0x47, 0x02, 0x69, 0x0A, 0xB1, 0x11, 0x68, 0x31, 0xB9, 0x6F, 0xF0, 0x04, 0x00, + 0x70, 0x47, 0x01, 0xF1, 0x0C, 0x02, 0xC9, 0x68, 0x39, 0xB1, 0x81, 0x42, 0xF9, 0xD1, 0xC9, 0x68, + 0x11, 0x60, 0x00, 0x21, 0x01, 0x61, 0x08, 0x46, 0x70, 0x47, 0x6F, 0xF0, 0x03, 0x00, 0x70, 0x47, + 0xC1, 0x7D, 0x01, 0x29, 0x05, 0xD1, 0x49, 0x07, 0x11, 0xF8, 0x2D, 0x2F, 0x42, 0xF0, 0x02, 0x02, + 0x0A, 0x70, 0x14, 0x49, 0x02, 0x68, 0x4A, 0x60, 0x42, 0x68, 0x8A, 0x60, 0x80, 0x7D, 0x08, 0x70, + 0x70, 0x47, 0x30, 0xB4, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0xF8, 0xE2, 0x1F, 0xC2, 0x89, 0x0D, 0x48, + 0xCC, 0x07, 0x43, 0x68, 0x03, 0xD0, 0x02, 0x24, 0x44, 0x70, 0x20, 0x46, 0x04, 0xE0, 0x01, 0x24, + 0x44, 0x70, 0x52, 0x1C, 0x92, 0xB2, 0x20, 0x46, 0x30, 0xBC, 0x18, 0x47, 0x4F, 0xF0, 0x00, 0x50, + 0x90, 0xF8, 0xE2, 0x10, 0x03, 0x48, 0x02, 0x78, 0x91, 0x42, 0x01, 0xD1, 0x80, 0x68, 0x00, 0x47, + 0x70, 0x47, 0x00, 0x00, 0x2C, 0x08, 0x10, 0x00, 0x53, 0xEA, 0x02, 0x0C, 0x00, 0xF0, 0x69, 0x80, + 0x2D, 0xE9, 0xF0, 0x4B, 0x4F, 0xF0, 0x00, 0x06, 0x00, 0x2B, 0x1F, 0xBF, 0xB3, 0xFA, 0x83, 0xF5, + 0x03, 0xFA, 0x05, 0xF4, 0x24, 0xFA, 0x05, 0xF6, 0x5E, 0x40, 0x12, 0xBF, 0x16, 0x43, 0xB2, 0xFA, + 0x82, 0xF5, 0x02, 0xFA, 0x05, 0xF4, 0xC5, 0xF1, 0x20, 0x05, 0x1E, 0xBF, 0x22, 0xFA, 0x05, 0xFC, + 0x44, 0xEA, 0x0C, 0x04, 0x20, 0x35, 0x56, 0xEA, 0x04, 0x4C, 0x4F, 0xEA, 0x14, 0x44, 0x18, 0xBF, + 0x64, 0x1C, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x00, 0x09, 0x90, 0x42, 0x71, 0xEB, 0x03, 0x0C, + 0x39, 0xD3, 0x00, 0x29, 0x19, 0xBF, 0xB1, 0xFA, 0x81, 0xF7, 0x01, 0xFA, 0x07, 0xF6, 0xB0, 0xFA, + 0x80, 0xF7, 0x00, 0xFA, 0x07, 0xF6, 0xC7, 0xF1, 0x20, 0x07, 0x1E, 0xBF, 0x20, 0xFA, 0x07, 0xFC, + 0x46, 0xEA, 0x0C, 0x06, 0x20, 0x37, 0xB6, 0xFB, 0xF4, 0xFC, 0xA7, 0xEB, 0x05, 0x07, 0x10, 0x3F, + 0x07, 0xF0, 0x1F, 0x0B, 0xCB, 0xF1, 0x20, 0x06, 0x0C, 0xFA, 0x0B, 0xFB, 0x2C, 0xFA, 0x06, 0xF6, + 0x44, 0xBF, 0xB3, 0x46, 0x00, 0x26, 0x20, 0x2F, 0xA4, 0xBF, 0x5E, 0x46, 0x4F, 0xF0, 0x00, 0x0B, + 0x5B, 0xEA, 0x06, 0x0C, 0x08, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, 0x19, 0xEB, 0x0B, 0x09, 0xAB, 0xFB, + 0x02, 0x7C, 0x48, 0xEB, 0x06, 0x08, 0xC0, 0x1B, 0x06, 0xFB, 0x02, 0xCC, 0x0B, 0xFB, 0x03, 0xCC, + 0x71, 0xEB, 0x0C, 0x01, 0xC1, 0xE7, 0x0B, 0x46, 0x02, 0x46, 0x41, 0x46, 0x48, 0x46, 0xBD, 0xE8, + 0xF0, 0x8B, 0x13, 0xB5, 0x4F, 0xF0, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x01, 0xAF, 0xF3, 0x00, 0x80, + 0xBD, 0xE8, 0x1C, 0x40, 0x70, 0x47, 0xB2, 0xF1, 0x20, 0x03, 0x0A, 0xD5, 0xC2, 0xF1, 0x20, 0x03, + 0x01, 0xFA, 0x02, 0xF1, 0x20, 0xFA, 0x03, 0xF3, 0x00, 0xFA, 0x02, 0xF0, 0x41, 0xEA, 0x03, 0x01, + 0x70, 0x47, 0x00, 0xFA, 0x03, 0xF1, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0x10, 0xB5, 0x4C, 0x10, + 0x84, 0xEA, 0x53, 0x04, 0x04, 0xD5, 0x40, 0x42, 0xC1, 0xF1, 0x00, 0x01, 0x38, 0xBF, 0x49, 0x1E, + 0x1B, 0x42, 0x04, 0xD5, 0x52, 0x42, 0xC3, 0xF1, 0x00, 0x03, 0x38, 0xBF, 0x5B, 0x1E, 0xFF, 0xF7, + 0x63, 0xFF, 0x14, 0xF0, 0x80, 0x4F, 0x04, 0xD0, 0x40, 0x42, 0xC1, 0xF1, 0x00, 0x01, 0x38, 0xBF, + 0x49, 0x1E, 0x14, 0xF0, 0x00, 0x4F, 0x04, 0xD0, 0x52, 0x42, 0xC3, 0xF1, 0x00, 0x03, 0x38, 0xBF, + 0x5B, 0x1E, 0x10, 0xBD, 0x03, 0x2A, 0x40, 0xF2, 0x30, 0x80, 0x10, 0xF0, 0x03, 0x0C, 0x00, 0xF0, + 0x15, 0x80, 0x11, 0xF8, 0x01, 0x3B, 0xBC, 0xF1, 0x02, 0x0F, 0x62, 0x44, 0x98, 0xBF, 0x11, 0xF8, + 0x01, 0xCB, 0x00, 0xF8, 0x01, 0x3B, 0x38, 0xBF, 0x11, 0xF8, 0x01, 0x3B, 0xA2, 0xF1, 0x04, 0x02, + 0x98, 0xBF, 0x00, 0xF8, 0x01, 0xCB, 0x38, 0xBF, 0x00, 0xF8, 0x01, 0x3B, 0x11, 0xF0, 0x03, 0x03, + 0x00, 0xF0, 0x25, 0x80, 0x08, 0x3A, 0xC0, 0xF0, 0x08, 0x80, 0x51, 0xF8, 0x04, 0x3B, 0x08, 0x3A, + 0x51, 0xF8, 0x04, 0xCB, 0xA0, 0xE8, 0x08, 0x10, 0xF5, 0xE7, 0x12, 0x1D, 0x5C, 0xBF, 0x51, 0xF8, + 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0xAF, 0xF3, 0x00, 0x80, 0xD2, 0x07, 0x24, 0xBF, 0x11, 0xF8, + 0x01, 0x3B, 0x11, 0xF8, 0x01, 0xCB, 0x48, 0xBF, 0x11, 0xF8, 0x01, 0x2B, 0x24, 0xBF, 0x00, 0xF8, + 0x01, 0x3B, 0x00, 0xF8, 0x01, 0xCB, 0x48, 0xBF, 0x00, 0xF8, 0x01, 0x2B, 0x70, 0x47, 0x10, 0xB5, + 0x20, 0x3A, 0xC0, 0xF0, 0x0B, 0x80, 0xB1, 0xE8, 0x18, 0x50, 0x20, 0x3A, 0xA0, 0xE8, 0x18, 0x50, + 0xB1, 0xE8, 0x18, 0x50, 0xA0, 0xE8, 0x18, 0x50, 0xBF, 0xF4, 0xF5, 0xAF, 0x5F, 0xEA, 0x02, 0x7C, + 0x24, 0xBF, 0xB1, 0xE8, 0x18, 0x50, 0xA0, 0xE8, 0x18, 0x50, 0x44, 0xBF, 0x18, 0xC9, 0x18, 0xC0, + 0xBD, 0xE8, 0x10, 0x40, 0x5F, 0xEA, 0x82, 0x7C, 0x24, 0xBF, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, + 0x04, 0x3B, 0x08, 0xBF, 0x70, 0x47, 0xD2, 0x07, 0x28, 0xBF, 0x31, 0xF8, 0x02, 0x3B, 0x48, 0xBF, + 0x11, 0xF8, 0x01, 0x2B, 0x28, 0xBF, 0x20, 0xF8, 0x02, 0x3B, 0x48, 0xBF, 0x00, 0xF8, 0x01, 0x2B, + 0x70, 0x47, 0x02, 0xF0, 0xFF, 0x03, 0x43, 0xEA, 0x03, 0x22, 0x42, 0xEA, 0x02, 0x42, 0x00, 0xF0, + 0x02, 0xB8, 0x4F, 0xF0, 0x00, 0x02, 0x04, 0x29, 0xC0, 0xF0, 0x12, 0x80, 0x10, 0xF0, 0x03, 0x0C, + 0x00, 0xF0, 0x1B, 0x80, 0xCC, 0xF1, 0x04, 0x0C, 0xBC, 0xF1, 0x02, 0x0F, 0x18, 0xBF, 0x00, 0xF8, + 0x01, 0x2B, 0xA8, 0xBF, 0x20, 0xF8, 0x02, 0x2B, 0xA1, 0xEB, 0x0C, 0x01, 0x00, 0xF0, 0x0D, 0xB8, + 0x5F, 0xEA, 0xC1, 0x7C, 0x24, 0xBF, 0x00, 0xF8, 0x01, 0x2B, 0x00, 0xF8, 0x01, 0x2B, 0x48, 0xBF, + 0x00, 0xF8, 0x01, 0x2B, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x02, 0x00, 0xB5, 0x13, 0x46, 0x94, 0x46, + 0x96, 0x46, 0x20, 0x39, 0x22, 0xBF, 0xA0, 0xE8, 0x0C, 0x50, 0xA0, 0xE8, 0x0C, 0x50, 0xB1, 0xF1, + 0x20, 0x01, 0xBF, 0xF4, 0xF7, 0xAF, 0x09, 0x07, 0x28, 0xBF, 0xA0, 0xE8, 0x0C, 0x50, 0x48, 0xBF, + 0x0C, 0xC0, 0x5D, 0xF8, 0x04, 0xEB, 0x89, 0x00, 0x28, 0xBF, 0x40, 0xF8, 0x04, 0x2B, 0x08, 0xBF, + 0x70, 0x47, 0x48, 0xBF, 0x20, 0xF8, 0x02, 0x2B, 0x11, 0xF0, 0x80, 0x4F, 0x18, 0xBF, 0x00, 0xF8, + 0x01, 0x2B, 0x70, 0x47, 0x04, 0x46, 0xAF, 0xF3, 0x00, 0x80, 0x20, 0x46, 0xE9, 0xF7, 0x36, 0xFC, + 0x01, 0x49, 0x18, 0x20, 0xAB, 0xBE, 0xFE, 0xE7, 0x26, 0x00, 0x02, 0x00, 0x70, 0x47, 0x00, 0x00, + 0x01, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x3C, 0x05, 0x00, 0x22, 0x2D, 0xE9, 0xF0, 0x41, + 0x0F, 0x4F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0x4F, 0xF0, 0x00, 0x56, 0x08, 0xFA, 0x04, 0xF0, + 0xC5, 0xB2, 0x96, 0xF8, 0x2F, 0x00, 0x28, 0x42, 0x0C, 0xD0, 0x96, 0xF8, 0x39, 0x00, 0x28, 0x42, + 0x08, 0xD0, 0x57, 0xF8, 0x24, 0x00, 0x00, 0xB1, 0x80, 0x47, 0x96, 0xF8, 0x2F, 0x00, 0xA8, 0x43, + 0x86, 0xF8, 0x2F, 0x00, 0x64, 0x1C, 0x06, 0x2C, 0xE8, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, + 0x1C, 0x88, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x4F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, + 0x4F, 0xF0, 0x00, 0x56, 0x08, 0xFA, 0x04, 0xF0, 0xC5, 0xB2, 0x96, 0xF8, 0x2E, 0x00, 0x28, 0x42, + 0x0C, 0xD0, 0x96, 0xF8, 0x38, 0x00, 0x28, 0x42, 0x08, 0xD0, 0x57, 0xF8, 0x24, 0x00, 0x00, 0xB1, + 0x80, 0x47, 0x96, 0xF8, 0x2E, 0x00, 0xA8, 0x43, 0x86, 0xF8, 0x2E, 0x00, 0x64, 0x1C, 0x06, 0x2C, + 0xE8, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, 0xFC, 0x87, 0x10, 0x00, 0x01, 0x21, 0x81, 0x40, + 0xC8, 0xB2, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x33, 0x10, 0x01, 0x42, 0x01, 0xD0, 0x01, 0x20, + 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x01, 0x49, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, + 0x3C, 0x05, 0x00, 0x22, 0x00, 0x48, 0x70, 0x47, 0x59, 0x07, 0x10, 0x00, 0x07, 0x48, 0x41, 0x78, + 0x49, 0xB1, 0x80, 0x78, 0x38, 0xB1, 0x06, 0x48, 0x80, 0x79, 0x01, 0x28, 0x03, 0xD1, 0x05, 0x48, + 0x00, 0x78, 0x01, 0x28, 0x00, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x4C, 0x07, 0x10, 0x00, + 0xEC, 0x06, 0x10, 0x00, 0x04, 0x05, 0x10, 0x00, 0x03, 0x48, 0x41, 0x78, 0x11, 0xB9, 0x80, 0x78, + 0x00, 0x28, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x4C, 0x07, 0x10, 0x00, 0x01, 0x48, 0x00, 0x78, + 0x70, 0x47, 0x00, 0x00, 0x50, 0x06, 0x10, 0x00, 0xC0, 0x6E, 0x70, 0x47, 0x90, 0xF8, 0x73, 0x00, + 0x70, 0x47, 0x90, 0xF8, 0x72, 0x00, 0x70, 0x47, 0x05, 0x48, 0x41, 0x78, 0x82, 0x78, 0x11, 0x44, + 0x02, 0x78, 0xC0, 0x78, 0x10, 0x44, 0x08, 0x18, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, + 0x0C, 0x06, 0x10, 0x00, 0x70, 0xB5, 0xD0, 0xE9, 0x00, 0x21, 0x4C, 0x08, 0x4F, 0xEA, 0x32, 0x03, + 0x96, 0x18, 0x41, 0xEB, 0x01, 0x05, 0x33, 0x43, 0x2C, 0x43, 0x13, 0x43, 0x0C, 0x43, 0xC0, 0xE9, + 0x00, 0x34, 0x70, 0xBD, 0x01, 0xEB, 0x81, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0x29, 0x30, 0x70, 0x47, + 0x02, 0x4A, 0x12, 0x78, 0x51, 0x43, 0x00, 0xEB, 0x41, 0x00, 0x70, 0x47, 0xBA, 0x06, 0x10, 0x00, + 0x01, 0xEB, 0x81, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0x29, 0x30, 0x70, 0x47, 0x02, 0x4A, 0x12, 0x78, + 0x51, 0x43, 0x00, 0xEB, 0x41, 0x00, 0x70, 0x47, 0xBA, 0x06, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xBE, 0x94, 0xFE, 0xFF, 0x27, 0xC4, + 0xFE, 0xFF, 0x59, 0xF2, 0xFE, 0xFF, 0x6B, 0x1F, 0xFF, 0xFF, 0x81, 0x4B, 0xFF, 0xFF, 0xC5, 0x76, + 0xFF, 0xFF, 0x67, 0xA1, 0xFF, 0xFF, 0x97, 0xCB, 0xFF, 0xFF, 0x88, 0xF5, 0xFF, 0xFF, 0x6C, 0x1F, + 0x00, 0x00, 0x76, 0x49, 0x00, 0x00, 0xD9, 0x73, 0x00, 0x00, 0xC6, 0x9E, 0x00, 0x00, 0x6D, 0xCA, + 0x00, 0x00, 0xFC, 0xF6, 0x00, 0x00, 0x9A, 0x24, 0x01, 0x00, 0x66, 0x53, 0x01, 0x00, 0xA3, 0x8D, + 0x00, 0x00, 0x71, 0x74, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0xA2, 0x4F, 0x00, 0x00, 0xC8, 0x42, + 0x00, 0x00, 0x0C, 0x39, 0x00, 0x00, 0x21, 0x32, 0x00, 0x00, 0xD2, 0x2D, 0x00, 0x00, 0x00, 0x2C, + 0x00, 0x00, 0x9B, 0x2C, 0x00, 0x00, 0xA9, 0x2F, 0x00, 0x00, 0x40, 0x35, 0x00, 0x00, 0x8B, 0x3D, + 0x00, 0x00, 0xCB, 0x48, 0x00, 0x00, 0x59, 0x57, 0x00, 0x00, 0xAD, 0x69, 0x00, 0x00, 0x65, 0x80, + 0x00, 0x00, 0x30, 0x11, 0x00, 0x00, 0x4C, 0x1C, 0x00, 0x00, 0x2D, 0x29, 0x00, 0x00, 0x86, 0x37, + 0x00, 0x00, 0x24, 0x47, 0x00, 0x00, 0xE8, 0x57, 0x00, 0x00, 0xC4, 0x69, 0x00, 0x00, 0xB5, 0x7C, + 0x00, 0x00, 0xC4, 0x90, 0x00, 0x00, 0x03, 0xA6, 0x00, 0x00, 0x8F, 0xBC, 0x00, 0x00, 0x8C, 0xD4, + 0x00, 0x00, 0x29, 0xEE, 0x00, 0x00, 0x9C, 0x09, 0x01, 0x00, 0x2B, 0x27, 0x01, 0x00, 0x24, 0x47, + 0x01, 0x00, 0xE6, 0x69, 0x01, 0x00, 0x98, 0x08, 0x00, 0x00, 0x26, 0x0E, 0x00, 0x00, 0x97, 0x14, + 0x00, 0x00, 0xC3, 0x1B, 0x00, 0x00, 0x92, 0x23, 0x00, 0x00, 0xF4, 0x2B, 0x00, 0x00, 0xE2, 0x34, + 0x00, 0x00, 0x5A, 0x3E, 0x00, 0x00, 0x62, 0x48, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x48, 0x5E, + 0x00, 0x00, 0x46, 0x6A, 0x00, 0x00, 0x14, 0x77, 0x00, 0x00, 0xCE, 0x84, 0x00, 0x00, 0x95, 0x93, + 0x00, 0x00, 0x92, 0xA3, 0x00, 0x00, 0xF3, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x0C, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE4, 0x40, 0x10, 0x00, 0x30, 0x46, 0x10, 0x00, 0x2B, 0xF5, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xF4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x21, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4B, 0xF4, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAD, 0xF4, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xC3, 0xF4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF7, 0xF4, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xF9, 0xF4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFB, 0xF4, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xFD, 0xF4, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xF4, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x29, 0xF5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6F, 0xF5, 0x00, 0x00, + 0x6B, 0xF5, 0x00, 0x00, 0xD5, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x31, 0xF7, 0x00, 0x00, + 0x6B, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, + 0x6B, 0xF5, 0x00, 0x00, 0x9F, 0xF5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC1, 0xF5, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF6, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0xF6, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x49, 0xF6, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x7F, 0xF6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2D, 0xF7, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x5D, 0xF7, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xBB, 0xF7, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xD1, 0xF7, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0xF8, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA7, 0xF8, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x8B, 0xF9, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xCB, 0xF9, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5F, 0xF8, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x25, 0xF9, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xF7, 0x00, 0x00, + 0x81, 0xF7, 0x00, 0x00, 0x8B, 0xF7, 0x00, 0x00, 0x9B, 0xF7, 0x00, 0x00, 0xAB, 0xF7, 0x00, 0x00, + 0x61, 0xFB, 0x00, 0x00, 0x83, 0xFB, 0x00, 0x00, 0x8B, 0xFB, 0x00, 0x00, 0xAB, 0xFB, 0x00, 0x00, + 0x0D, 0xFC, 0x00, 0x00, 0x33, 0xFC, 0x00, 0x00, 0x43, 0xFC, 0x00, 0x00, 0x55, 0xFC, 0x00, 0x00, + 0x67, 0xFC, 0x00, 0x00, 0x79, 0xFC, 0x00, 0x00, 0x8B, 0xFC, 0x00, 0x00, 0x9D, 0xFC, 0x00, 0x00, + 0xAF, 0xFC, 0x00, 0x00, 0xC1, 0xFC, 0x00, 0x00, 0xD3, 0xFC, 0x00, 0x00, 0xE5, 0xFC, 0x00, 0x00, + 0x85, 0x86, 0x60, 0x61, 0xD0, 0x02, 0x0F, 0x01, 0x00, 0xA6, 0x02, 0x0F, 0x03, 0x00, 0xA8, 0x02, + 0x0B, 0x03, 0x00, 0x72, 0x00, 0x0B, 0x01, 0x00, 0x73, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xB4, 0x6C, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB4, 0x70, 0x10, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xB4, 0x74, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x19, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xB4, 0x7C, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x61, 0xFA, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xB4, 0x7E, 0x10, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF1, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1D, 0x2F, 0x01, 0x00, 0xC7, 0x2E, 0x01, 0x00, 0xB3, 0x41, 0x01, 0x00, + 0x81, 0x26, 0x01, 0x00, 0x01, 0x31, 0x01, 0x00, 0x5D, 0x3C, 0x01, 0x00, 0x81, 0x27, 0x01, 0x00, + 0xBB, 0x2F, 0x01, 0x00, 0xC9, 0x41, 0x01, 0x00, 0x00, 0x04, 0x40, 0x00, 0x10, 0x21, 0x00, 0x00, + 0x00, 0x1F, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x04, 0x06, 0x00, + 0x08, 0x02, 0x50, 0x00, 0x60, 0x02, 0x0C, 0x0C, 0x00, 0x00, 0x60, 0x02, 0x0C, 0x30, 0x0C, 0x1A, + 0x31, 0x10, 0x0F, 0x0F, 0x00, 0x00, 0x2F, 0x00, 0x01, 0x00, 0xAA, 0x2C, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x07, 0x01, 0x26, 0x26, 0x12, 0x12, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x3C, 0x20, 0x3D, 0xD0, 0x41, 0xEC, 0x41, 0x08, 0x42, 0x1C, 0x42, 0x30, 0x42, + 0x44, 0x42, 0x60, 0x42, 0x74, 0x42, 0x88, 0x42, 0xA4, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x01, 0x02, + 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x80, 0x2D, 0x00, 0x00, 0x80, 0x36, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80, + 0x5A, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x80, + 0x82, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x80, 0xD8, 0x00, 0x00, 0x00, + 0xC3, 0x00, 0x00, 0x80, 0xF5, 0x00, 0x00, 0x80, 0xEE, 0x00, 0x00, 0x00, 0x29, 0x01, 0x00, 0x80, + 0x32, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x80, 0x68, 0x01, 0x00, 0x00, + 0x73, 0x01, 0x00, 0x80, 0x45, 0x01, 0x00, 0x80, 0x5E, 0x01, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xAB, 0x01, 0x00, 0x80, 0x9D, 0x01, 0x00, 0x80, 0x86, 0x01, 0x00, 0x00, 0xF1, 0x01, 0x00, 0x80, + 0xEA, 0x01, 0x00, 0x00, 0xDC, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x80, 0x49, 0x02, 0x00, 0x80, + 0x52, 0x02, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x7F, 0x02, 0x00, 0x80, 0x08, 0x02, 0x00, 0x00, + 0x13, 0x02, 0x00, 0x80, 0x25, 0x02, 0x00, 0x80, 0x3E, 0x02, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00, + 0xCB, 0x02, 0x00, 0x80, 0xFD, 0x02, 0x00, 0x80, 0xE6, 0x02, 0x00, 0x00, 0x91, 0x02, 0x00, 0x80, + 0x8A, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0xA7, 0x02, 0x00, 0x80, 0x60, 0x03, 0x00, 0x00, + 0x7B, 0x03, 0x00, 0x80, 0x4D, 0x03, 0x00, 0x80, 0x56, 0x03, 0x00, 0x00, 0x21, 0x03, 0x00, 0x80, + 0x3A, 0x03, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x17, 0x03, 0x00, 0x80, 0xF9, 0x03, 0x00, 0x80, + 0xE2, 0x03, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0xCF, 0x03, 0x00, 0x80, 0xB8, 0x03, 0x00, 0x00, + 0xA3, 0x03, 0x00, 0x80, 0x95, 0x03, 0x00, 0x80, 0x8E, 0x03, 0x00, 0x00, 0x89, 0x04, 0x00, 0x80, + 0x92, 0x04, 0x00, 0x00, 0xA4, 0x04, 0x00, 0x00, 0xBF, 0x04, 0x00, 0x80, 0xC8, 0x04, 0x00, 0x00, + 0xD3, 0x04, 0x00, 0x80, 0xE5, 0x04, 0x00, 0x80, 0xFE, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, + 0x0B, 0x04, 0x00, 0x80, 0x3D, 0x04, 0x00, 0x80, 0x26, 0x04, 0x00, 0x00, 0x51, 0x04, 0x00, 0x80, + 0x4A, 0x04, 0x00, 0x00, 0x7C, 0x04, 0x00, 0x00, 0x67, 0x04, 0x00, 0x80, 0xA0, 0x05, 0x00, 0x00, + 0xBB, 0x05, 0x00, 0x80, 0x8D, 0x05, 0x00, 0x80, 0x96, 0x05, 0x00, 0x00, 0xE1, 0x05, 0x00, 0x80, + 0xFA, 0x05, 0x00, 0x00, 0xCC, 0x05, 0x00, 0x00, 0xD7, 0x05, 0x00, 0x80, 0x39, 0x05, 0x00, 0x80, + 0x22, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x00, 0x0F, 0x05, 0x00, 0x80, 0x78, 0x05, 0x00, 0x00, + 0x63, 0x05, 0x00, 0x80, 0x55, 0x05, 0x00, 0x80, 0x4E, 0x05, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x00, + 0xDB, 0x06, 0x00, 0x80, 0xED, 0x06, 0x00, 0x80, 0xF6, 0x06, 0x00, 0x00, 0x81, 0x06, 0x00, 0x80, + 0x9A, 0x06, 0x00, 0x00, 0xAC, 0x06, 0x00, 0x00, 0xB7, 0x06, 0x00, 0x80, 0x59, 0x06, 0x00, 0x80, + 0x42, 0x06, 0x00, 0x00, 0x74, 0x06, 0x00, 0x00, 0x6F, 0x06, 0x00, 0x80, 0x18, 0x06, 0x00, 0x00, + 0x03, 0x06, 0x00, 0x80, 0x35, 0x06, 0x00, 0x80, 0x2E, 0x06, 0x00, 0x00, 0xE9, 0x07, 0x00, 0x80, + 0xF2, 0x07, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0xDF, 0x07, 0x00, 0x80, 0xA8, 0x07, 0x00, 0x00, + 0xB3, 0x07, 0x00, 0x80, 0x85, 0x07, 0x00, 0x80, 0x9E, 0x07, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, + 0x6B, 0x07, 0x00, 0x80, 0x5D, 0x07, 0x00, 0x80, 0x46, 0x07, 0x00, 0x00, 0x31, 0x07, 0x00, 0x80, + 0x2A, 0x07, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x80, 0x09, 0x09, 0x00, 0x80, + 0x12, 0x09, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00, 0x3F, 0x09, 0x00, 0x80, 0x48, 0x09, 0x00, 0x00, + 0x53, 0x09, 0x00, 0x80, 0x65, 0x09, 0x00, 0x80, 0x7E, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, + 0x8B, 0x09, 0x00, 0x80, 0xBD, 0x09, 0x00, 0x80, 0xA6, 0x09, 0x00, 0x00, 0xD1, 0x09, 0x00, 0x80, + 0xCA, 0x09, 0x00, 0x00, 0xFC, 0x09, 0x00, 0x00, 0xE7, 0x09, 0x00, 0x80, 0x20, 0x08, 0x00, 0x00, + 0x3B, 0x08, 0x00, 0x80, 0x0D, 0x08, 0x00, 0x80, 0x16, 0x08, 0x00, 0x00, 0x61, 0x08, 0x00, 0x80, + 0x7A, 0x08, 0x00, 0x00, 0x4C, 0x08, 0x00, 0x00, 0x57, 0x08, 0x00, 0x80, 0xB9, 0x08, 0x00, 0x80, + 0xA2, 0x08, 0x00, 0x00, 0x94, 0x08, 0x00, 0x00, 0x8F, 0x08, 0x00, 0x80, 0xF8, 0x08, 0x00, 0x00, + 0xE3, 0x08, 0x00, 0x80, 0xD5, 0x08, 0x00, 0x80, 0xCE, 0x08, 0x00, 0x00, 0x40, 0x0B, 0x00, 0x00, + 0x5B, 0x0B, 0x00, 0x80, 0x6D, 0x0B, 0x00, 0x80, 0x76, 0x0B, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x80, + 0x1A, 0x0B, 0x00, 0x00, 0x2C, 0x0B, 0x00, 0x00, 0x37, 0x0B, 0x00, 0x80, 0xD9, 0x0B, 0x00, 0x80, + 0xC2, 0x0B, 0x00, 0x00, 0xF4, 0x0B, 0x00, 0x00, 0xEF, 0x0B, 0x00, 0x80, 0x98, 0x0B, 0x00, 0x00, + 0x83, 0x0B, 0x00, 0x80, 0xB5, 0x0B, 0x00, 0x80, 0xAE, 0x0B, 0x00, 0x00, 0x69, 0x0A, 0x00, 0x80, + 0x72, 0x0A, 0x00, 0x00, 0x44, 0x0A, 0x00, 0x00, 0x5F, 0x0A, 0x00, 0x80, 0x28, 0x0A, 0x00, 0x00, + 0x33, 0x0A, 0x00, 0x80, 0x05, 0x0A, 0x00, 0x80, 0x1E, 0x0A, 0x00, 0x00, 0xF0, 0x0A, 0x00, 0x00, + 0xEB, 0x0A, 0x00, 0x80, 0xDD, 0x0A, 0x00, 0x80, 0xC6, 0x0A, 0x00, 0x00, 0xB1, 0x0A, 0x00, 0x80, + 0xAA, 0x0A, 0x00, 0x00, 0x9C, 0x0A, 0x00, 0x00, 0x87, 0x0A, 0x00, 0x80, 0x80, 0x0D, 0x00, 0x00, + 0x9B, 0x0D, 0x00, 0x80, 0xAD, 0x0D, 0x00, 0x80, 0xB6, 0x0D, 0x00, 0x00, 0xC1, 0x0D, 0x00, 0x80, + 0xDA, 0x0D, 0x00, 0x00, 0xEC, 0x0D, 0x00, 0x00, 0xF7, 0x0D, 0x00, 0x80, 0x19, 0x0D, 0x00, 0x80, + 0x02, 0x0D, 0x00, 0x00, 0x34, 0x0D, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x80, 0x58, 0x0D, 0x00, 0x00, + 0x43, 0x0D, 0x00, 0x80, 0x75, 0x0D, 0x00, 0x80, 0x6E, 0x0D, 0x00, 0x00, 0xA9, 0x0C, 0x00, 0x80, + 0xB2, 0x0C, 0x00, 0x00, 0x84, 0x0C, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x80, 0xE8, 0x0C, 0x00, 0x00, + 0xF3, 0x0C, 0x00, 0x80, 0xC5, 0x0C, 0x00, 0x80, 0xDE, 0x0C, 0x00, 0x00, 0x30, 0x0C, 0x00, 0x00, + 0x2B, 0x0C, 0x00, 0x80, 0x1D, 0x0C, 0x00, 0x80, 0x06, 0x0C, 0x00, 0x00, 0x71, 0x0C, 0x00, 0x80, + 0x6A, 0x0C, 0x00, 0x00, 0x5C, 0x0C, 0x00, 0x00, 0x47, 0x0C, 0x00, 0x80, 0xC9, 0x0F, 0x00, 0x80, + 0xD2, 0x0F, 0x00, 0x00, 0xE4, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x80, 0x88, 0x0F, 0x00, 0x00, + 0x93, 0x0F, 0x00, 0x80, 0xA5, 0x0F, 0x00, 0x80, 0xBE, 0x0F, 0x00, 0x00, 0x50, 0x0F, 0x00, 0x00, + 0x4B, 0x0F, 0x00, 0x80, 0x7D, 0x0F, 0x00, 0x80, 0x66, 0x0F, 0x00, 0x00, 0x11, 0x0F, 0x00, 0x80, + 0x0A, 0x0F, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, 0x27, 0x0F, 0x00, 0x80, 0xE0, 0x0E, 0x00, 0x00, + 0xFB, 0x0E, 0x00, 0x80, 0xCD, 0x0E, 0x00, 0x80, 0xD6, 0x0E, 0x00, 0x00, 0xA1, 0x0E, 0x00, 0x80, + 0xBA, 0x0E, 0x00, 0x00, 0x8C, 0x0E, 0x00, 0x00, 0x97, 0x0E, 0x00, 0x80, 0x79, 0x0E, 0x00, 0x80, + 0x62, 0x0E, 0x00, 0x00, 0x54, 0x0E, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x80, 0x38, 0x0E, 0x00, 0x00, + 0x23, 0x0E, 0x00, 0x80, 0x15, 0x0E, 0x00, 0x80, 0x0E, 0x0E, 0x00, 0x00, 0x4C, 0x74, 0x01, 0x00, + 0x00, 0x04, 0x10, 0x00, 0x38, 0x04, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x84, 0x74, 0x01, 0x00, + 0x00, 0xFC, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x84, 0x74, 0x01, 0x00, + 0x38, 0x08, 0x10, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x01, 0xFF, 0x01, 0x75, + 0x14, 0x90, 0x5F, 0x01, 0x32, 0x01, 0x32, 0x02, 0x29, 0x08, 0x41, 0xA9, 0x08, 0x09, 0x1A, 0x0C, + 0xB2, 0x64, 0x29, 0x0C, 0x69, 0x48, 0x29, 0x04, 0x0A, 0x11, 0x04, 0x10, 0x01, 0xFF, 0x01, 0x42, + 0x07, 0x8D, 0xF0, 0x01, 0x20, 0x04, 0x49, 0x10, 0xAA, 0xFF, 0x0C, 0x59, 0x01, 0x01, 0x1D, 0x04, + 0x50, 0x90, 0xD0, 0x03, 0x30, 0xB5, 0x72, 0xB6, 0x01, 0x23, 0x0C, 0x4D, 0x2B, 0x60, 0x0C, 0x4A, + 0x00, 0x24, 0x81, 0xB1, 0x13, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x00, 0xF0, 0x1F, 0x00, 0x81, 0xF8, + 0x6A, 0x00, 0x07, 0x48, 0x1C, 0x38, 0x03, 0x60, 0x01, 0x68, 0x00, 0x29, 0xFC, 0xD1, 0x14, 0x60, + 0x2C, 0x60, 0x62, 0xB6, 0x30, 0xBD, 0x14, 0x60, 0xED, 0xE7, 0x00, 0x00, 0xC0, 0x1B, 0x00, 0x22, + 0x78, 0x0D, 0x00, 0x22, 0xF6, 0x63, 0xE8, 0xA2, 0x97, 0x02, 0x00, 0x00, 0x09, 0x9C, 0x17, 0x5D, + 0x68, 0xFD, 0xFF, 0xFF, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x0F, 0x6F, 0x08, 0x37, 0x04, 0x0F, 0x6F, 0x08, 0x37, 0x04, 0xB8, + 0x01, 0x01, 0x00, 0x01, 0x01, 0x20, 0x20, 0x50, 0xAA, 0x99, 0x00, 0x05, 0x00, 0x05, 0xC8, 0x00, + 0xC8, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x70, 0x00, 0x70, 0x00, 0x08, 0xB0, + 0x00, 0xB0, 0x00, 0x00, 0x03, 0xAA, 0x38, 0xC8, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x0F, 0x0F, 0x1F, 0x0F, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0xA0, 0x00, 0x64, 0x00, 0x64, 0x00, 0xD0, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x00, 0x02, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xA0, + 0x50, 0x4C, 0x26, 0x01, 0x08, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x06, 0x52, 0x4F, + 0x04, 0xD8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x08, 0xB0, 0x06, 0x03, 0x03, 0x00, 0x00, + 0xBB, 0xBB, 0xC8, 0x00, 0xC8, 0x00, 0x88, 0x88, 0x00, 0x00, 0xE9, 0xA6, 0x1A, 0x1F, 0x04, 0xD8, + 0x18, 0x32, 0x00, 0x20, 0x00, 0x24, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x24, 0x60, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x16, 0x50, 0x4F, 0x04, 0x18, 0x00, 0x30, 0x00, 0x06, + 0x00, 0x2F, 0x00, 0x40, 0x10, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x66, 0x9E, 0x1F, 0x98, 0x18, 0x01, 0x01, 0x30, 0x00, + 0x30, 0x00, 0x40, 0x00, 0x10, 0x00, 0x21, 0x03, 0x00, 0x00, 0x1F, 0x21, 0x01, 0x00, 0x00, 0x1F, + 0x00, 0x01, 0x28, 0x00, 0x99, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x64, 0x00, 0x64, 0x00, 0xD0, 0x00, 0x80, 0x0C, 0xF0, 0x0A, + 0xD0, 0x00, 0x00, 0x15, 0x00, 0x12, 0x50, 0x01, 0x50, 0x01, 0x00, 0x15, 0x00, 0x12, 0x50, 0x01, + 0x80, 0x0C, 0xF0, 0x0A, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x0E, 0x02, 0x0B, 0x14, 0x0F, 0x02, 0x64, 0x90, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x14, 0x14, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x80, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0x02, 0x40, 0x90, 0x01, + 0x90, 0x01, 0x80, 0x00, 0x80, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x64, 0x00, 0x80, 0x01, 0x64, 0x00, 0x80, 0x01, 0x96, 0x00, + 0x64, 0x00, 0x20, 0x00, 0x02, 0x00, 0x96, 0x00, 0x64, 0x00, 0x64, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x64, 0x00, 0x05, 0x01, 0xF4, 0x01, 0x2C, 0x01, 0x02, 0xFF, 0x7F, 0xFF, 0x7F, 0x02, + 0x32, 0x64, 0x00, 0x00, 0x02, 0x02, 0xA2, 0x20, 0x00, 0x29, 0x64, 0x00, 0x64, 0x00, 0xC8, 0x00, + 0x58, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x32, 0x00, 0x20, 0x00, 0x14, 0x0A, 0x84, 0x03, + 0x64, 0x00, 0x00, 0x04, 0x02, 0x00, 0x20, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0E, + 0x10, 0x00, 0x40, 0x00, 0x18, 0x00, 0x00, 0x01, 0x62, 0x84, 0x40, 0x01, 0x20, 0x00, 0x10, 0x00, + 0x64, 0x00, 0x64, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0x02, 0x00, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x0C, 0x04, 0x20, 0x00, 0x10, 0x10, 0x20, 0x00, 0x20, 0x00, 0x96, 0x00, + 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x00, 0x40, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x28, 0x02, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x14, 0x00, 0x01, 0x03, 0x01, 0x0A, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x70, 0x00, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7D, 0x03, 0x64, 0x00, 0x00, 0x02, 0x10, 0x01, 0x00, 0x02, 0x64, 0x00, + 0x06, 0x64, 0x00, 0x64, 0x00, 0x0E, 0x00, 0x05, 0x00, 0x10, 0x50, 0x00, 0x32, 0x00, 0x10, 0x21, + 0x0F, 0x02, 0x10, 0x1F, 0x00, 0x0A, 0x00, 0x14, 0x81, 0x11, 0x1A, 0x00, 0x16, 0x00, 0x00, 0x10, + 0x0A, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x0A, 0xE8, 0x10, 0x00, 0x40, 0x00, 0x40, 0x94, 0x94, + 0x28, 0x88, 0x62, 0x10, 0x00, 0x64, 0x00, 0x10, 0x00, 0x30, 0x00, 0x0A, 0x00, 0x18, 0x00, 0x05, + 0x20, 0x05, 0x20, 0x18, 0x20, 0xD8, 0x05, 0x32, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0xC8, 0x00, 0xC8, 0x00, 0x0A, 0x0A, 0x64, 0x00, 0x64, 0x00, + 0x01, 0x03, 0x64, 0x00, 0x64, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x96, 0x00, 0x0A, 0x06, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x32, 0x1A, + 0xFA, 0x00, 0x20, 0x05, 0x20, 0x0A, 0x05, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x00, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2E, 0x03, 0x50, 0x00, 0x50, 0x00, 0x2C, 0x01, 0x32, 0xFF, 0x7F, 0x0B, + 0x01, 0x32, 0x00, 0x20, 0x03, 0x00, 0x0A, 0x20, 0x14, 0x05, 0xF8, 0x00, 0x00, 0x00, 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, 0x03, 0x04, 0x00, 0x01, 0x02, 0x03, 0x50, 0x01, + 0x50, 0x01, 0x50, 0x01, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x96, 0x7D, 0x6E, 0x67, 0x65, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x64, 0x65, 0x67, 0x6E, 0x7D, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x13, 0x22, 0x22, + 0x22, 0x00, 0x00, 0x0F, 0x00, 0x28, 0x00, 0x3C, 0x00, 0x50, 0x00, 0xA0, 0x00, 0x40, 0x01, 0xE0, + 0x01, 0xD0, 0x02, 0xBF, 0x03, 0x5F, 0x04, 0xFF, 0x04, 0x4F, 0x05, 0x63, 0x05, 0x77, 0x05, 0x90, + 0x05, 0x0F, 0x00, 0x28, 0x00, 0x3C, 0x00, 0x50, 0x00, 0xA0, 0x00, 0x40, 0x01, 0xE0, 0x01, 0xD0, + 0x02, 0xC0, 0x03, 0x00, 0x05, 0x3F, 0x06, 0x2F, 0x07, 0x1F, 0x08, 0xBF, 0x08, 0x5F, 0x09, 0xAF, + 0x09, 0xC3, 0x09, 0xD7, 0x09, 0xF5, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x19, 0x00, 0x28, 0x00, 0x6C, + 0x00, 0x27, 0x01, 0xD1, 0x01, 0xD0, 0x02, 0xC6, 0x03, 0x72, 0x04, 0x21, 0x05, 0x69, 0x05, 0x86, + 0x05, 0x95, 0x05, 0x9F, 0x05, 0x00, 0x00, 0x0F, 0x00, 0x1C, 0x00, 0x28, 0x00, 0x78, 0x00, 0x1C, + 0x01, 0xC6, 0x01, 0xBE, 0x02, 0xAE, 0x03, 0x00, 0x05, 0x4F, 0x06, 0x44, 0x07, 0x39, 0x08, 0xDE, + 0x08, 0x8A, 0x09, 0xD8, 0x09, 0xE3, 0x09, 0xF1, 0x09, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x64, 0x80, 0x10, 0xE5, 0x00, 0x00, + 0x64, 0x80, 0xA4, 0x00, 0xA7, 0x00, 0xB2, 0x00, 0xC3, 0x00, 0xDB, 0x00, 0xFA, 0x00, 0x1F, 0x01, + 0x4A, 0x01, 0x7A, 0x01, 0xB0, 0x01, 0xEC, 0x01, 0x2B, 0x02, 0x6F, 0x02, 0xB6, 0x02, 0x01, 0x03, + 0x4D, 0x03, 0x9C, 0x03, 0xEC, 0x03, 0x3D, 0x04, 0x8E, 0x04, 0xDF, 0x04, 0x2E, 0x05, 0x7C, 0x05, + 0xC8, 0x05, 0x11, 0x06, 0x56, 0x06, 0x98, 0x06, 0xD5, 0x06, 0x0E, 0x07, 0x42, 0x07, 0x6F, 0x07, + 0x97, 0x07, 0xB9, 0x07, 0xD5, 0x07, 0xE9, 0x07, 0xF7, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xF7, 0x07, + 0xE9, 0x07, 0xD5, 0x07, 0xB9, 0x07, 0x97, 0x07, 0x6F, 0x07, 0x42, 0x07, 0x0E, 0x07, 0xD5, 0x06, + 0x98, 0x06, 0x56, 0x06, 0x11, 0x06, 0xC8, 0x05, 0x7C, 0x05, 0x2E, 0x05, 0xDF, 0x04, 0x8E, 0x04, + 0x3D, 0x04, 0xEC, 0x03, 0x9C, 0x03, 0x4D, 0x03, 0x01, 0x03, 0xB6, 0x02, 0x6F, 0x02, 0x2B, 0x02, + 0xEC, 0x01, 0xB0, 0x01, 0x7A, 0x01, 0x4A, 0x01, 0x1F, 0x01, 0xFA, 0x00, 0xDB, 0x00, 0xC3, 0x00, + 0xB2, 0x00, 0xA7, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6A, 0x00, 0x6C, 0x00, 0x72, 0x00, 0x7C, 0x00, 0x89, 0x00, 0x9A, 0x00, 0xAF, 0x00, + 0xC7, 0x00, 0xE2, 0x00, 0x01, 0x01, 0x22, 0x01, 0x46, 0x01, 0x6D, 0x01, 0x95, 0x01, 0xC0, 0x01, + 0xED, 0x01, 0x1B, 0x02, 0x4A, 0x02, 0x7A, 0x02, 0xAA, 0x02, 0xDB, 0x02, 0x0B, 0x03, 0x3B, 0x03, + 0x6B, 0x03, 0x99, 0x03, 0xC7, 0x03, 0xF2, 0x03, 0x1C, 0x04, 0x44, 0x04, 0x69, 0x04, 0x8C, 0x04, + 0xAC, 0x04, 0xC9, 0x04, 0xE3, 0x04, 0xF9, 0x04, 0x0C, 0x05, 0x1B, 0x05, 0x26, 0x05, 0x2E, 0x05, + 0x32, 0x05, 0x32, 0x05, 0x2E, 0x05, 0x26, 0x05, 0x1B, 0x05, 0x0C, 0x05, 0xF9, 0x04, 0xE3, 0x04, + 0xC9, 0x04, 0xAC, 0x04, 0x8C, 0x04, 0x69, 0x04, 0x44, 0x04, 0x1C, 0x04, 0xF2, 0x03, 0xC7, 0x03, + 0x99, 0x03, 0x6B, 0x03, 0x3B, 0x03, 0x0B, 0x03, 0xDB, 0x02, 0xAA, 0x02, 0x7A, 0x02, 0x4A, 0x02, + 0x1B, 0x02, 0xED, 0x01, 0xC0, 0x01, 0x95, 0x01, 0x6D, 0x01, 0x46, 0x01, 0x22, 0x01, 0x01, 0x01, + 0xE2, 0x00, 0xC7, 0x00, 0xAF, 0x00, 0x9A, 0x00, 0x89, 0x00, 0x7C, 0x00, 0x72, 0x00, 0x6C, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xCD, 0x00, 0xCD, 0x00, 0xCD, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x08, 0x0C, 0x0D, 0x0F, 0x0F, 0x0F, 0x0E, 0x0E, + 0x0E, 0x0D, 0x0D, 0x0D, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x64, 0x9A, 0x1F, 0x18, 0x18, 0x01, 0x01, 0x30, 0x00, + 0x30, 0x00, 0x40, 0x00, 0x10, 0x00, 0x21, 0x07, 0x00, 0x00, 0x1F, 0x20, 0x03, 0x00, 0x00, 0x1F, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x50, 0x10, 0x10, 0xB0, 0x20, 0xFF, 0xD0, 0x00, 0x06, 0x14, + 0x14, 0x2A, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x6E, 0x6E, + 0x47, 0x1A, 0x38, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x1E, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x24, 0x94, 0x1F, 0x18, 0x18, 0x01, 0x00, 0x25, 0x00, + 0x25, 0x00, 0x50, 0x00, 0x24, 0x00, 0x70, 0x01, 0x00, 0x00, 0x1F, 0x80, 0x01, 0x00, 0x00, 0x1F, + 0x00, 0x01, 0x10, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4E, 0xD3, 0x25, 0xD2, +}; + +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.c b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.c new file mode 100644 index 000000000000..0fe5f0c3d5c2 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.c @@ -0,0 +1,953 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS functions for getting Initialization Data * + * * + ************************************************************************** + ************************************************************************** + * + */ +/*! + * \file ftsCompensation.c + * \brief Contains all the function to work with Initialization Data + */ + +#include "ftsCompensation.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsFrame.h" +#include "ftsHardware.h" +#include "ftsIO.h" +#include "ftsSoftware.h" +#include "ftsTime.h" +#include "ftsTool.h" + + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/serio.h> +#include <linux/time.h> +#include <linux/delay.h> +#include <linux/ctype.h> + + +/** + * Request to the FW to load the specified Initialization Data + * @param type type of Initialization data to load @link load_opt Load Host + * Data Option @endlink + * @return OK if success or an error code which specify the type of error + */ +int requestCompensationData(u8 type) +{ + int ret = ERROR_OP_NOT_ALLOW; + int retry = 0; + + pr_info("%s: Requesting compensation data...\n", __func__); + while (retry < RETRY_COMP_DATA_READ) { + ret = writeSysCmd(SYS_CMD_LOAD_DATA, &type, 1); + /* send request to load in memory the Compensation Data */ + if (ret < OK) { + pr_err("%s: failed at %d attemp!\n", + __func__, retry + 1); + retry += 1; + } else { + pr_info("%s: Request Compensation data FINISHED!\n", + __func__); + return OK; + } + } + + pr_err("%s: Requesting compensation data... ERROR %08X\n", + __func__, ret | ERROR_REQU_COMP_DATA); + return ret | ERROR_REQU_COMP_DATA; +} + + +/** + * Read Initialization Data Header and check that the type loaded match + * with the one previously requested + * @param type type of Initialization data requested @link load_opt Load Host + * Data Option @endlink + * @param header pointer to DataHeader variable which will contain the header + * @param address pointer to a variable which will contain the updated address + * to the next data + * @return OK if success or an error code which specify the type of error + */ +int readCompensationDataHeader(u8 type, DataHeader *header, u64 *address) +{ + u64 offset = ADDR_FRAMEBUFFER; + u8 data[COMP_DATA_HEADER]; + int ret; + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data, + COMP_DATA_HEADER, DUMMY_FRAMEBUFFER); + if (ret < OK) { /* i2c function have already a retry mechanism */ + pr_err("%s: error while reading data header ERROR %08X\n", + __func__, ret); + return ret; + } + + pr_info("Read Data Header done!\n"); + + if (data[0] != HEADER_SIGNATURE) { + pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n", + __func__, data[0], HEADER_SIGNATURE, + ERROR_WRONG_DATA_SIGN); + return ERROR_WRONG_DATA_SIGN; + } + + + if (data[1] != type) { + pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n", + __func__, data[1], type, ERROR_DIFF_DATA_TYPE); + return ERROR_DIFF_DATA_TYPE; + } + + pr_info("Type = %02X of Compensation data OK!\n", type); + + header->type = type; + + *address = offset + COMP_DATA_HEADER; + + return OK; +} + + +/** + * Read MS Global Initialization data from the buffer such as Cx1 + * @param address pointer to a variable which contain the address from where + * to read the data and will contain the updated address to the next data + * @param global pointer to MutualSenseData variable which will contain the MS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readMutualSenseGlobalData(u64 *address, MutualSenseData *global) +{ + u8 data[COMP_DATA_GLOBAL]; + int ret; + + pr_info("Address for Global data= %llx\n", *address); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data, + COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading info data ERROR %08X\n", + __func__, ret); + return ret; + } + pr_info("Global data Read !\n"); + + global->header.force_node = data[0]; + global->header.sense_node = data[1]; + global->cx1 = data[2]; + /* all other bytes are reserved atm */ + + pr_info("force_len = %d sense_len = %d CX1 = %d\n", + global->header.force_node, global->header.sense_node, + global->cx1); + + *address += COMP_DATA_GLOBAL; + return OK; +} + + +/** + * Read MS Initialization data for each node from the buffer + * @param address a variable which contain the address from where to read the + * data + * @param node pointer to MutualSenseData variable which will contain the MS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readMutualSenseNodeData(u64 address, MutualSenseData *node) +{ + int ret; + int size = node->header.force_node * node->header.sense_node; + + pr_info("Address for Node data = %llx\n", address); + + node->node_data = (i8 *)kmalloc(size * (sizeof(i8)), GFP_KERNEL); + + if (node->node_data == NULL) { + pr_err("%s: can not allocate node_data... ERROR %08X", + __func__, ERROR_ALLOC); + return ERROR_ALLOC; + } + + pr_info("Node Data to read %d bytes\n", size); + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, + node->node_data, size, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading node data ERROR %08X\n", + __func__, ret); + kfree(node->node_data); + return ret; + } + node->node_data_size = size; + + pr_info("Read node data OK!\n"); + + return size; +} + +/** + * Perform all the steps to read the necessary info for MS Initialization data + * from the buffer and store it in a MutualSenseData variable + * @param type type of MS Initialization data to read @link load_opt Load Host + * Data Option @endlink + * @param data pointer to MutualSenseData variable which will contain the MS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readMutualSenseCompensationData(u8 type, MutualSenseData *data) +{ + int ret; + u64 address; + + data->node_data = NULL; + + if (!(type == LOAD_CX_MS_TOUCH || type == LOAD_CX_MS_LOW_POWER || + type == LOAD_CX_MS_KEY || type == LOAD_CX_MS_FORCE)) { + pr_err("%s: Choose a MS type of compensation data ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + ret = requestCompensationData(type); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_REQU_COMP_DATA); + return ret | ERROR_REQU_COMP_DATA; + } + + ret = readCompensationDataHeader(type, &(data->header), &address); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_HEADER); + return ret | ERROR_COMP_DATA_HEADER; + } + + ret = readMutualSenseGlobalData(&address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL); + return ret | ERROR_COMP_DATA_GLOBAL; + } + + ret = readMutualSenseNodeData(address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE); + return ret | ERROR_COMP_DATA_NODE; + } + + return OK; +} + +/** + * Read SS Global Initialization data from the buffer such as Ix1/Cx1 for force + * and sense + * @param address pointer to a variable which contain the address from where + * to read the data and will contain the updated address to the next data + * @param global pointer to MutualSenseData variable which will contain the SS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readSelfSenseGlobalData(u64 *address, SelfSenseData *global) +{ + int ret; + u8 data[COMP_DATA_GLOBAL]; + + pr_info("Address for Global data= %llx\n", *address); + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data, + COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading the data... ERROR %08X\n", + __func__, ret); + return ret; + } + + pr_info("Global data Read !\n"); + + + global->header.force_node = data[0]; + global->header.sense_node = data[1]; + global->f_ix1 = data[2]; + global->s_ix1 = data[3]; + global->f_cx1 = (i8)data[4]; + global->s_cx1 = (i8)data[5]; + global->f_max_n = data[6]; + global->s_max_n = data[7]; + + pr_info("force_len = %d sense_len = %d f_ix1 = %d s_ix1 = %d f_cx1 = %d s_cx1 = %d\n", + global->header.force_node, global->header.sense_node, + global->f_ix1, global->s_ix1, global->f_cx1, global->s_cx1); + pr_info("max_n = %d s_max_n = %d\n", global->f_max_n, + global->s_max_n); + + + *address += COMP_DATA_GLOBAL; + + return OK; +} + +/** + * Read SS Initialization data for each node of force and sense channels from + * the buffer + * @param address a variable which contain the address from where to read the + * data + * @param node pointer to SelfSenseData variable which will contain the SS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readSelfSenseNodeData(u64 address, SelfSenseData *node) +{ + int size = node->header.force_node * 2 + node->header.sense_node * 2; + u8 data[size]; + int ret; + + node->ix2_fm = (u8 *)kmalloc(node->header.force_node * (sizeof(u8)), + GFP_KERNEL); + if (node->ix2_fm == NULL) { + pr_err("%s: can not allocate memory for ix2_fm... ERROR %08X", + __func__, ERROR_ALLOC); + return ERROR_ALLOC; + } + + node->cx2_fm = (i8 *)kmalloc(node->header.force_node * (sizeof(i8)), + GFP_KERNEL); + if (node->cx2_fm == NULL) { + pr_err("%s: can not allocate memory for cx2_fm ... ERROR %08X", + __func__, ERROR_ALLOC); + kfree(node->ix2_fm); + return ERROR_ALLOC; + } + node->ix2_sn = (u8 *)kmalloc(node->header.sense_node * (sizeof(u8)), + GFP_KERNEL); + if (node->ix2_sn == NULL) { + pr_err("%s: can not allocate memory for ix2_sn ERROR %08X", + __func__, ERROR_ALLOC); + kfree(node->ix2_fm); + kfree(node->cx2_fm); + return ERROR_ALLOC; + } + node->cx2_sn = (i8 *)kmalloc(node->header.sense_node * (sizeof(i8)), + GFP_KERNEL); + if (node->cx2_sn == NULL) { + pr_err("%s: can not allocate memory for cx2_sn ERROR %08X", + __func__, ERROR_ALLOC); + kfree(node->ix2_fm); + kfree(node->cx2_fm); + kfree(node->ix2_sn); + return ERROR_ALLOC; + } + + + pr_info("Address for Node data = %llx\n", address); + + pr_info("Node Data to read %d bytes\n", size); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data, + size, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading data... ERROR %08X\n", + __func__, ret); + kfree(node->ix2_fm); + kfree(node->cx2_fm); + kfree(node->ix2_sn); + kfree(node->cx2_sn); + return ret; + } + + pr_info("Read node data ok!\n"); + + memcpy(node->ix2_fm, data, node->header.force_node); + memcpy(node->ix2_sn, &data[node->header.force_node], + node->header.sense_node); + memcpy(node->cx2_fm, &data[node->header.force_node + + node->header.sense_node], + node->header.force_node); + memcpy(node->cx2_sn, &data[node->header.force_node * 2 + + node->header.sense_node], + node->header.sense_node); + + return OK; +} + +/** + * Perform all the steps to read the necessary info for SS Initialization data + * from the buffer and store it in a SelfSenseData variable + * @param type type of SS Initialization data to read @link load_opt Load Host + * Data Option @endlink + * @param data pointer to SelfSenseData variable which will contain the SS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readSelfSenseCompensationData(u8 type, SelfSenseData *data) +{ + int ret; + u64 address; + + data->ix2_fm = NULL; + data->cx2_fm = NULL; + data->ix2_sn = NULL; + data->cx2_sn = NULL; + + if (!(type == LOAD_CX_SS_TOUCH || type == LOAD_CX_SS_TOUCH_IDLE || + type == LOAD_CX_SS_KEY || type == LOAD_CX_SS_FORCE)) { + pr_err("%s: Choose a SS type of compensation data ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + ret = requestCompensationData(type); + if (ret < 0) { + pr_err("%s: error while requesting data... ERROR %08X\n", + __func__, ERROR_REQU_COMP_DATA); + return ret | ERROR_REQU_COMP_DATA; + } + + ret = readCompensationDataHeader(type, &(data->header), &address); + if (ret < 0) { + pr_err("%s: error while reading data header... ERROR %08X\n", + __func__, ERROR_COMP_DATA_HEADER); + return ret | ERROR_COMP_DATA_HEADER; + } + + ret = readSelfSenseGlobalData(&address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL); + return ret | ERROR_COMP_DATA_GLOBAL; + } + + ret = readSelfSenseNodeData(address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE); + return ret | ERROR_COMP_DATA_NODE; + } + + return OK; +} + +/** + * Read TOT MS Global Initialization data from the buffer such as number of + * force and sense channels + * @param address pointer to a variable which contain the address from where + * to read the data and will contain the updated address to the next data + * @param global pointer to a variable which will contain the TOT MS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readTotMutualSenseGlobalData(u64 *address, TotMutualSenseData *global) +{ + int ret; + u8 data[COMP_DATA_GLOBAL]; + + pr_info("Address for Global data= %llx\n", *address); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data, + COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading info data ERROR %08X\n", + __func__, ret); + return ret; + } + pr_info("Global data Read !\n"); + + global->header.force_node = data[0]; + global->header.sense_node = data[1]; + /* all other bytes are reserved atm */ + + pr_info("force_len = %d sense_len = %d\n", + global->header.force_node, global->header.sense_node); + + *address += COMP_DATA_GLOBAL; + return OK; +} + + +/** + * Read TOT MS Initialization data for each node from the buffer + * @param address a variable which contain the address from where to read the + * data + * @param node pointer to MutualSenseData variable which will contain the TOT + * MS initialization data + * @return OK if success or an error code which specify the type of error + */ +int readTotMutualSenseNodeData(u64 address, TotMutualSenseData *node) +{ + int ret, i; + int size = node->header.force_node * node->header.sense_node; + int toRead = size * sizeof(u16); + u8 data[toRead]; + + pr_info("Address for Node data = %llx\n", address); + + node->node_data = (short *)kmalloc(size * (sizeof(short)), GFP_KERNEL); + + if (node->node_data == NULL) { + pr_err("%s: can not allocate node_data... ERROR %08X", + __func__, ERROR_ALLOC); + return ERROR_ALLOC; + } + + pr_info("Node Data to read %d bytes\n", size); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data, + toRead, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading node data ERROR %08X\n", + __func__, ret); + kfree(node->node_data); + return ret; + } + node->node_data_size = size; + + for (i = 0; i < size; i++) + node->node_data[i] = ((short)data[i * 2 + 1]) << 8 | + data[i * 2]; + + pr_info("Read node data OK!\n"); + + return size; +} + +/** + * Perform all the steps to read the necessary info for TOT MS Initialization + * data from the buffer and store it in a TotMutualSenseData variable + * @param type type of TOT MS Initialization data to read @link load_opt Load + * Host Data Option @endlink + * @param data pointer to a variable which will contain the TOT MS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readTotMutualSenseCompensationData(u8 type, TotMutualSenseData *data) +{ + int ret; + u64 address; + + data->node_data = NULL; + + if (!(type == LOAD_PANEL_CX_TOT_MS_TOUCH || type == + LOAD_PANEL_CX_TOT_MS_LOW_POWER || + type == LOAD_PANEL_CX_TOT_MS_KEY || + type == LOAD_PANEL_CX_TOT_MS_FORCE)) { + pr_err("%s: Choose a TOT MS type of compensation data ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + ret = requestCompensationData(type); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_REQU_COMP_DATA); + return ret | ERROR_REQU_COMP_DATA; + } + + ret = readCompensationDataHeader(type, &(data->header), &address); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_HEADER); + return ret | ERROR_COMP_DATA_HEADER; + } + + ret = readTotMutualSenseGlobalData(&address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL); + return ret | ERROR_COMP_DATA_GLOBAL; + } + + ret = readTotMutualSenseNodeData(address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE); + return ret | ERROR_COMP_DATA_NODE; + } + + return OK; +} + +/** + * Read TOT SS Global Initialization data from the buffer such as number of + * force and sense channels + * @param address pointer to a variable which contain the address from where + * to read the data and will contain the updated address to the next data + * @param global pointer to a variable which will contain the TOT SS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readTotSelfSenseGlobalData(u64 *address, TotSelfSenseData *global) +{ + int ret; + u8 data[COMP_DATA_GLOBAL]; + + pr_info("Address for Global data= %llx\n", *address); + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data, + COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading the data... ERROR %08X\n", + __func__, ret); + return ret; + } + + pr_info("Global data Read !\n"); + + + global->header.force_node = data[0]; + global->header.sense_node = data[1]; + + + pr_info("force_len = %d sense_len = %d\n", + global->header.force_node, global->header.sense_node); + + + *address += COMP_DATA_GLOBAL; + + return OK; +} + +/** + * Read TOT SS Global Initialization data from the buffer such as number of + * force and sense channels + * @param address pointer to a variable which contain the address from where + * to read the data and will contain the updated address to the next data + * @param node pointer to a variable which will contain the TOT SS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) +{ + int size = node->header.force_node * 2 + node->header.sense_node * 2; + int toRead = size * 2; /* *2 2 bytes each node */ + u8 data[toRead]; + int ret, i, j = 0; + + node->ix_fm = (u16 *)kmalloc(node->header.force_node * (sizeof(u16)), + GFP_KERNEL); + if (node->ix_fm == NULL) { + pr_err("%s: can not allocate memory for ix2_fm... ERROR %08X", + __func__, ERROR_ALLOC); + return ERROR_ALLOC; + } + + node->cx_fm = (short *)kmalloc(node->header.force_node * + (sizeof(short)), GFP_KERNEL); + if (node->cx_fm == NULL) { + pr_err("%s: can not allocate memory for cx2_fm ... ERROR %08X", + __func__, ERROR_ALLOC); + kfree(node->ix_fm); + return ERROR_ALLOC; + } + node->ix_sn = (u16 *)kmalloc(node->header.sense_node * (sizeof(u16)), + GFP_KERNEL); + if (node->ix_sn == NULL) { + pr_err("%s: can not allocate memory for ix2_sn ERROR %08X", + __func__, ERROR_ALLOC); + kfree(node->ix_fm); + kfree(node->cx_fm); + return ERROR_ALLOC; + } + node->cx_sn = (short *)kmalloc(node->header.sense_node * + (sizeof(short)), GFP_KERNEL); + if (node->cx_sn == NULL) { + pr_err("%s: can not allocate memory for cx2_sn ERROR %08X", + __func__, ERROR_ALLOC); + kfree(node->ix_fm); + kfree(node->cx_fm); + kfree(node->ix_sn); + return ERROR_ALLOC; + } + + + pr_info("Address for Node data = %llx\n", address); + + pr_info("Node Data to read %d bytes\n", size); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data, + toRead, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading data... ERROR %08X\n", + __func__, ret); + kfree(node->ix_fm); + kfree(node->cx_fm); + kfree(node->ix_sn); + kfree(node->cx_sn); + return ret; + } + + pr_info("Read node data ok!\n"); + + j = 0; + for (i = 0; i < node->header.force_node; i++) { + node->ix_fm[i] = ((u16)data[j + 1]) << 8 | data[j]; + j += 2; + } + + for (i = 0; i < node->header.sense_node; i++) { + node->ix_sn[i] = ((u16)data[j + 1]) << 8 | data[j]; + j += 2; + } + + for (i = 0; i < node->header.force_node; i++) { + node->cx_fm[i] = ((short)data[j + 1]) << 8 | data[j]; + j += 2; + } + + for (i = 0; i < node->header.sense_node; i++) { + node->cx_sn[i] = ((short)data[j + 1]) << 8 | data[j]; + j += 2; + } + + if (j != toRead) + pr_err("%s: parsed a wrong number of bytes %d!=%d\n", + __func__, j, toRead); + + return OK; +} + +/** + * Perform all the steps to read the necessary info for TOT SS Initialization + * data from the buffer and store it in a TotSelfSenseData variable + * @param type type of TOT MS Initialization data to read @link load_opt Load + * Host Data Option @endlink + * @param data pointer to a variable which will contain the TOT MS + * initialization data + * @return OK if success or an error code which specify the type of error + */ +int readTotSelfSenseCompensationData(u8 type, TotSelfSenseData *data) +{ + int ret; + u64 address; + + data->ix_fm = NULL; + data->cx_fm = NULL; + data->ix_sn = NULL; + data->cx_sn = NULL; + + if (!(type == LOAD_PANEL_CX_TOT_SS_TOUCH || type == + LOAD_PANEL_CX_TOT_SS_TOUCH_IDLE || type == + LOAD_PANEL_CX_TOT_SS_KEY || + type == LOAD_PANEL_CX_TOT_SS_FORCE)) { + pr_err("%s: Choose a TOT SS type of compensation data ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + ret = requestCompensationData(type); + if (ret < 0) { + pr_err("%s: error while requesting data... ERROR %08X\n", + __func__, ERROR_REQU_COMP_DATA); + return ret | ERROR_REQU_COMP_DATA; + } + + ret = readCompensationDataHeader(type, &(data->header), &address); + if (ret < 0) { + pr_err("%s: error while reading data header... ERROR %08X\n", + __func__, ERROR_COMP_DATA_HEADER); + return ret | ERROR_COMP_DATA_HEADER; + } + + ret = readTotSelfSenseGlobalData(&address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL); + return ret | ERROR_COMP_DATA_GLOBAL; + } + + ret = readTotSelfSenseNodeData(address, data); + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE); + return ret | ERROR_COMP_DATA_NODE; + } + + return OK; +} + + +/** + * Read Initialization Data Header for the Coefficients and check that the type + * loaded match with the one previously requested + * @param type type of Coefficients data requested @link load_opt Load Host + * Data Option @endlink + * @param msHeader pointer to DataHeader variable for the MS Coefficients + * @param ssHeader pointer to DataHeader variable for the SS Coefficients + * @param address pointer to a variable which will contain the updated address + * to the next data + * @return OK if success or an error code which specify the type of error + */ +int readSensitivityCoeffHeader(u8 type, DataHeader *msHeader, + DataHeader *ssHeader, u64 *address) +{ + u64 offset = ADDR_FRAMEBUFFER; + u8 data[SYNCFRAME_DATA_HEADER]; + int ret; + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data, + SYNCFRAME_DATA_HEADER, DUMMY_FRAMEBUFFER); + if (ret < OK) { /* i2c function have already a retry mechanism */ + pr_err("%s: error while reading data header ERROR %08X\n", + __func__, ret); + return ret; + } + + pr_info("Read Data Header done!\n"); + + if (data[0] != HEADER_SIGNATURE) { + pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n", + __func__, data[0], HEADER_SIGNATURE, + ERROR_WRONG_DATA_SIGN); + return ERROR_WRONG_DATA_SIGN; + } + + + if (data[1] != type) { + pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n", + __func__, data[1], type, ERROR_DIFF_DATA_TYPE); + return ERROR_DIFF_DATA_TYPE; + } + + pr_info("Type = %02X of Compensation data OK!\n", type); + + msHeader->type = type; + ssHeader->type = type; + + msHeader->force_node = data[5]; + msHeader->sense_node = data[6]; + pr_info("MS Force Len = %d Sense Len = %d\n", + msHeader->force_node, msHeader->sense_node); + + ssHeader->force_node = data[7]; + ssHeader->sense_node = data[8]; + pr_info("SS Force Len = %d Sense Len = %d\n", + ssHeader->force_node, ssHeader->sense_node); + + *address = offset + SYNCFRAME_DATA_HEADER; + + return OK; +} + + +/** + * Read MS and SS Sensitivity Coefficients for from the IC + * @param address a variable which contain the address from where to read the + * data + * @param msCoeff pointer to MutualSenseCoeff variable which will contain the + * MS Coefficient data + * @param ssCoeff pointer to SelfSenseCoeff variable which will contain the SS + * Coefficient data + * @return OK if success or an error code which specify the type of error + */ +int readSensitivityCoeffNodeData(u64 address, MutualSenseCoeff *msCoeff, + SelfSenseCoeff *ssCoeff) +{ + int size = msCoeff->header.force_node * msCoeff->header.sense_node + + (ssCoeff->header.force_node + ssCoeff->header.sense_node); + u8 data[size]; + int ret; + + msCoeff->node_data_size = msCoeff->header.force_node * + msCoeff->header.sense_node; + + msCoeff->ms_coeff = (u8 *)kmalloc(msCoeff->node_data_size * + (sizeof(u8)), GFP_KERNEL); + + ssCoeff->ss_force_coeff = (u8 *)kmalloc(ssCoeff->header.force_node * + (sizeof(u8)), GFP_KERNEL); + + ssCoeff->ss_sense_coeff = (u8 *)kmalloc(ssCoeff->header.sense_node * + (sizeof(u8)), GFP_KERNEL); + if (msCoeff->ms_coeff == NULL || + ssCoeff->ss_force_coeff == NULL || + ssCoeff->ss_sense_coeff == NULL) { + + pr_err("%s: can not allocate memory for coeff ERROR %08X", + __func__, ERROR_ALLOC); + + kfree(msCoeff->ms_coeff); + msCoeff->ms_coeff = NULL; + + kfree(ssCoeff->ss_force_coeff); + ssCoeff->ss_force_coeff = NULL; + + kfree(ssCoeff->ss_sense_coeff); + ssCoeff->ss_sense_coeff = NULL; + + return ERROR_ALLOC; + } + + pr_info("Address for Node data = %llx\n", address); + + pr_info("Node Data to read %d bytes\n", size); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data, + size, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading data... ERROR %08X\n", + __func__, ret); + kfree(msCoeff->ms_coeff); + msCoeff->ms_coeff = NULL; + kfree(ssCoeff->ss_force_coeff); + ssCoeff->ss_force_coeff = NULL; + kfree(ssCoeff->ss_sense_coeff); + ssCoeff->ss_sense_coeff = NULL; + return ret; + } + + pr_info("Read node data ok!\n"); + + memcpy(msCoeff->ms_coeff, data, msCoeff->node_data_size); + memcpy(ssCoeff->ss_force_coeff, &data[msCoeff->node_data_size], + ssCoeff->header.force_node); + memcpy(ssCoeff->ss_sense_coeff, &data[msCoeff->node_data_size + + ssCoeff->header.force_node], + ssCoeff->header.sense_node); + + return OK; +} + + +/** + * Perform all the steps to read Sensitivity Coefficients and store into the + * corresponding variables + * @param msCoeff pointer to a variable which will contain the MS Sensitivity + * Coefficients + * @param ssCoeff pointer to a variable which will contain the SS Sensitivity + * Coefficients + * @return OK if success or an error code which specify the type of error + */ +int readSensitivityCoefficientsData(MutualSenseCoeff *msCoeff, + SelfSenseCoeff *ssCoeff) +{ + int ret; + u64 address; + + msCoeff->ms_coeff = NULL; + ssCoeff->ss_force_coeff = NULL; + ssCoeff->ss_sense_coeff = NULL; + + + ret = requestCompensationData(LOAD_SENS_CAL_COEFF); + if (ret < OK) { + pr_err("%s: error while requesting data... ERROR %08X\n", + __func__, ERROR_REQU_COMP_DATA); + return ret | ERROR_REQU_COMP_DATA; + } + + ret = readSensitivityCoeffHeader(LOAD_SENS_CAL_COEFF, + &(msCoeff->header), &(ssCoeff->header), + &address); + if (ret < OK) { + pr_err("%s: error while reading data header... ERROR %08X\n", + __func__, ERROR_COMP_DATA_HEADER); + return ret | ERROR_COMP_DATA_HEADER; + } + + ret = readSensitivityCoeffNodeData(address, msCoeff, ssCoeff); + if (ret < OK) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE); + return ret | ERROR_COMP_DATA_NODE; + } + + return OK; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.h b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.h new file mode 100644 index 000000000000..34f4c9726695 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.h @@ -0,0 +1,165 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS functions for getting Initialization Data ** + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsCompensation.h + * \brief Contains all the definitions and structs to work with Initialization + * Data + */ + +#ifndef FTS_COMPENSATION_H +#define FTS_COMPENSATION_H + +#include "ftsCore.h" +#include "ftsSoftware.h" + + + +#define RETRY_COMP_DATA_READ 2 /* /< max number of attempts to read + * initialization data */ + + +/* Bytes dimension of Compensation Data Format */ + +#define COMP_DATA_HEADER DATA_HEADER /* /< size in bytes of + * initialization data header */ +#define COMP_DATA_GLOBAL (16 - COMP_DATA_HEADER) /* /< size in bytes + * of initialization + * data general info */ + + +#define HEADER_SIGNATURE 0xA5 /* /< signature used as starting byte of + * data loaded in memory */ + + + +/** + * Struct which contains the general info about Frames and Initialization Data + */ +typedef struct { + int force_node; /* /< Number of Force Channels in the + * frame/Initialization data */ + int sense_node; /* /< Number of Sense Channels in the + * frame/Initialization data */ + int type; /* /< Type of frame/Initialization data */ +} DataHeader; + +/** + * Struct which contains the MS Initialization data + */ +typedef struct { + DataHeader header; /* /< Header */ + i8 cx1; /* /< Cx1 value (can be negative)) */ + i8 *node_data; /* /< Pointer to an array of bytes which contains the + * CX2 data (can be negative) */ + int node_data_size; /* /< size of the data */ +} MutualSenseData; + + +/** + * Struct which contains the SS Initialization data + */ +typedef struct { + DataHeader header; /* /< Header */ + u8 f_ix1; /* /< IX1 Force */ + u8 s_ix1; /* /< IX1 Sense */ + i8 f_cx1; /* /< CX1 Force (can be negative) */ + i8 s_cx1; /* /< CX1 Sense (can be negative) */ + u8 f_max_n; /* /< Force MaxN */ + u8 s_max_n; /* /< Sense MaxN */ + + u8 *ix2_fm; /* /< pointer to an array of bytes which contains Force + * Ix2 data node */ + u8 *ix2_sn; /* /< pointer to an array of bytes which contains Sense + * Ix2 data node */ + i8 *cx2_fm; /* /< pointer to an array of bytes which contains Force + * Cx2 data node + * (can be negative) */ + i8 *cx2_sn; /* /< pointer to an array of bytes which contains Sense + * Cx2 data node + * (can be negative)) */ +} SelfSenseData; + +/** + * Struct which contains the TOT MS Initialization data + */ +typedef struct { + DataHeader header; /* /< Header */ + short *node_data; /* /< pointer to an array of ushort which + * contains TOT MS Initialization data */ + int node_data_size; /* /< size of data */ +} TotMutualSenseData; + +/** + * Struct which contains the TOT SS Initialization data + */ +typedef struct { + DataHeader header; /* /< Header */ + + u16 *ix_fm; /* /< pointer to an array of ushort which contains TOT + * SS IX Force data */ + u16 *ix_sn; /* /< pointer to an array of ushort which contains TOT + * SS IX Sense data */ + short *cx_fm; /* /< pointer to an array of ushort which contains TOT + * SS CX Force data + * (can be negative) */ + short *cx_sn; /* /< pointer to an array of ushort which contains TOT + * SS CX Sense data + * (can be negative) */ +} TotSelfSenseData; + +/** + * Struct which contains the Mutual Sense Sensitivity Calibration Coefficients + */ +typedef struct { + DataHeader header; /* /< Header */ + u8 *ms_coeff; /* /< Pointer to an array of bytes which contains the MS + * Sens coeff */ + int node_data_size; /* /< size of coefficients */ +} MutualSenseCoeff; + +/** + * Struct which contains the Self Sense Sensitivity Calibration Coefficients + */ +typedef struct { + DataHeader header; /* /< Header */ + u8 *ss_force_coeff; /* /< Pointer to an array of bytes which + * contains the SS Sens Force coeff */ + u8 *ss_sense_coeff; /* /< Pointer to an array of bytes which + * contains the SS Sens Sense coeff */ +} SelfSenseCoeff; + +int requestCompensationData(u8 type); +int readCompensationDataHeader(u8 type, DataHeader *header, u64 *address); +int readMutualSenseGlobalData(u64 *address, MutualSenseData *global); +int readMutualSenseNodeData(u64 address, MutualSenseData *node); +int readMutualSenseCompensationData(u8 type, MutualSenseData *data); +int readSelfSenseGlobalData(u64 *address, SelfSenseData *global); +int readSelfSenseNodeData(u64 address, SelfSenseData *node); +int readSelfSenseCompensationData(u8 type, SelfSenseData *data); +int readToTMutualSenseGlobalData(u64 *address, TotMutualSenseData *global); +int readToTMutualSenseNodeData(u64 address, TotMutualSenseData *node); +int readTotMutualSenseCompensationData(u8 type, TotMutualSenseData *data); +int readTotSelfSenseGlobalData(u64 *address, TotSelfSenseData *global); +int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node); +int readTotSelfSenseCompensationData(u8 type, TotSelfSenseData *data); +int readSensitivityCoeffHeader(u8 type, DataHeader *msHeader, + DataHeader *ssHeader, u64 *address); +int readSensitivityCoeffNodeData(u64 address, MutualSenseCoeff *msCoeff, + SelfSenseCoeff *ssCoeff); +int readSensitivityCoefficientsData(MutualSenseCoeff *msData, + SelfSenseCoeff *ssData); + +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCore.c b/drivers/input/touchscreen/stm/fts_lib/ftsCore.c new file mode 100644 index 000000000000..4dbdc4ee9085 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsCore.c @@ -0,0 +1,1181 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Core functions * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsCore.c + * \brief Contains the implementation of the Core functions + */ + +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include "ftsCompensation.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsIO.h" +#include "ftsTest.h" +#include "ftsTime.h" +#include "ftsTool.h" +#include "ftsFrame.h" + +/** @addtogroup system_info + * @{ + */ +SysInfo systemInfo; /* Global System Info variable, accessible in all the + * driver */ +/** @}*/ + +static int reset_gpio = GPIO_NOT_DEFINED;/* /< gpio number of the rest pin, + * the value is GPIO_NOT_DEFINED + * if the reset pin is not connected */ +static int system_reseted_up; /* /< flag checked during resume to understand + * if there was a system reset + * and restore the proper state */ +static int system_reseted_down; /* /< flag checked during suspend to understand + * if there was a system reset + * and restore the proper state */ +static int disable_irq_count = 1; /* /< count the number of call to + * disable_irq, + * start with 1 because at the boot IRQ + * are already disabled */ +spinlock_t fts_int; /* /< spinlock to control the access to the + * disable_irq_counter */ + + +/** + * Initialize core variables of the library. + * Must be called during the probe before any other lib function + * @param info pointer to fts_ts_info which contains info about the device and + * its hw setup + * @return OK if success or an error code which specify the type of error + */ +int initCore(struct fts_ts_info *info) +{ + int ret = OK; + + pr_info("%s: Initialization of the Core...\n", __func__); + ret |= openChannel(info->client); + ret |= resetErrorList(); + ret |= initTestToDo(); + setResetGpio(info->board->reset_gpio); + if (ret < OK) + pr_err("%s: Initialization Core ERROR %08X!\n", + __func__, ret); + else + pr_info("%s: Initialization Finished!\n", + __func__); + return ret; +} + +/** + * Set the reset_gpio variable with the actual gpio number of the board link to + * the reset pin + * @param gpio gpio number link to the reset pin of the IC + */ +void setResetGpio(int gpio) +{ + reset_gpio = gpio; + pr_info("setResetGpio: reset_gpio = %d\n", reset_gpio); +} + +/** + * Perform a system reset of the IC. + * If the reset pin is associated to a gpio, the function execute an hw reset + * (toggling of reset pin) otherwise send an hw command to the IC + * @return OK if success or an error code which specify the type of error + */ +int fts_system_reset(void) +{ + u8 readData[FIFO_EVENT_SIZE]; + int event_to_search; + int res = -1; + int i; + u8 data[1] = { SYSTEM_RESET_VALUE }; + + event_to_search = (int)EVT_ID_CONTROLLER_READY; + + pr_info("System resetting...\n"); + for (i = 0; i < RETRY_SYSTEM_RESET && res < 0; i++) { + resetErrorList(); + fts_disableInterrupt(); + /* disable interrupt before resetting to be able to get boot + * events */ + + if (reset_gpio == GPIO_NOT_DEFINED) + res = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, + ADDR_SYSTEM_RESET, data, ARRAY_SIZE( + data)); + else { + gpio_set_value(reset_gpio, 0); + mdelay(10); + gpio_set_value(reset_gpio, 1); + res = OK; + } + if (res < OK) + pr_err("fts_system_reset: ERROR %08X\n", ERROR_BUS_W); + else { + res = pollForEvent(&event_to_search, 1, readData, + GENERAL_TIMEOUT); + if (res < OK) + pr_err("fts_system_reset: ERROR %08X\n", res); + } + } + if (res < OK) { + pr_err("fts_system_reset...failed after 3 attempts: ERROR %08X\n", + (res | ERROR_SYSTEM_RESET_FAIL)); + return res | ERROR_SYSTEM_RESET_FAIL; + } else { + pr_debug("System reset DONE!\n"); + system_reseted_down = 1; + system_reseted_up = 1; + return OK; + } +} + +/** + * Return the value of system_resetted_down. + * @return the flag value: 0 if not set, 1 if set + */ +int isSystemResettedDown(void) +{ + return system_reseted_down; +} + +/** + * Return the value of system_resetted_up. + * @return the flag value: 0 if not set, 1 if set + */ +int isSystemResettedUp(void) +{ + return system_reseted_up; +} + + +/** + * Set the value of system_reseted_down flag + * @param val value to write in the flag + */ +void setSystemResetedDown(int val) +{ + system_reseted_down = val; +} + +/** + * Set the value of system_reseted_up flag + * @param val value to write in the flag + */ +void setSystemResetedUp(int val) +{ + system_reseted_up = val; +} + + +/** @addtogroup events_group + * @{ + */ + +/** + * Poll the FIFO looking for a specified event within a timeout. Support a + * retry mechanism. + * @param event_to_search pointer to an array of int where each element + * correspond to a byte of the event to find. + * If the element of the array has value -1, the byte of the event, + * in the same position of the element is ignored. + * @param event_bytes size of event_to_search + * @param readData pointer to an array of byte which will contain the event + * found + * @param time_to_wait time to wait before going in timeout + * @return OK if success or an error code which specify the type of error + */ +int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int + time_to_wait) +{ + int i, find, retry, count_err; + int time_to_count; + int err_handling = OK; + StopWatch clock; + + u8 cmd[1] = { FIFO_CMD_READONE }; + char temp[128] = { 0 }; + + find = 0; + retry = 0; + count_err = 0; + time_to_count = time_to_wait / TIMEOUT_RESOLUTION; + + startStopWatch(&clock); + while (find != 1 && retry < time_to_count && + fts_writeReadU8UX(cmd[0], 0, 0, readData, FIFO_EVENT_SIZE, + DUMMY_FIFO) + >= OK) { + /* Log of errors */ + if (readData[0] == EVT_ID_ERROR) { + pr_debug("%s\n", + printHex("ERROR EVENT = ", + readData, + FIFO_EVENT_SIZE, + temp, + sizeof(temp))); + memset(temp, 0, 128); + count_err++; + err_handling = errorHandler(readData, FIFO_EVENT_SIZE); + if ((err_handling & 0xF0FF0000) == + ERROR_HANDLER_STOP_PROC) { + pr_err("pollForEvent: forced to be stopped! ERROR %08X\n", + err_handling); + return err_handling; + } + } else { + if (readData[0] != EVT_ID_NOEVENT) { + pr_debug("%s\n", + printHex("READ EVENT = ", readData, + FIFO_EVENT_SIZE, + temp, + sizeof(temp))); + memset(temp, 0, 128); + } + if (readData[0] == EVT_ID_CONTROLLER_READY && + event_to_search[0] != EVT_ID_CONTROLLER_READY) { + pr_err("pollForEvent: Unmanned Controller Ready Event! Setting reset flags...\n"); + setSystemResetedUp(1); + setSystemResetedDown(1); + } + } + + find = 1; + + for (i = 0; i < event_bytes; i++) { + if (event_to_search[i] != -1 && (int)readData[i] != + event_to_search[i]) { + find = 0; + break; + } + } + + retry++; + mdelay(TIMEOUT_RESOLUTION); + } + stopStopWatch(&clock); + if ((retry >= time_to_count) && find != 1) { + pr_err("pollForEvent: ERROR %08X\n", ERROR_TIMEOUT); + return ERROR_TIMEOUT; + } else if (find == 1) { + pr_debug("%s\n", + printHex("FOUND EVENT = ", + readData, + FIFO_EVENT_SIZE, + temp, + sizeof(temp))); + memset(temp, 0, 128); + pr_debug("Event found in %d ms (%d iterations)! Number of errors found = %d\n", + elapsedMillisecond(&clock), retry, count_err); + return count_err; + } else { + pr_err("pollForEvent: ERROR %08X\n", ERROR_BUS_R); + return ERROR_BUS_R; + } +} + +/** @}*/ + +/** + * Check that the FW sent the echo even after a command was sent + * @param cmd pointer to an array of byte which contain the command previously + * sent + * @param size size of cmd + * @return OK if success or an error code which specify the type of error + */ +int checkEcho(u8 *cmd, int size) +{ + int ret, i; + int event_to_search[FIFO_EVENT_SIZE]; + u8 readData[FIFO_EVENT_SIZE]; + + + if (size < 1) { + pr_err("checkEcho: Error Size = %d not valid!\n", size); + return ERROR_OP_NOT_ALLOW; + } else { + if ((size + 3) > FIFO_EVENT_SIZE) + size = FIFO_EVENT_SIZE - 3; + /* Echo event 0x43 0x01 xx xx xx xx xx fifo_status + * therefore command with more than 5 bytes will be trunked */ + + event_to_search[0] = EVT_ID_STATUS_UPDATE; + event_to_search[1] = EVT_TYPE_STATUS_ECHO; + for (i = 2; i < size + 2; i++) + event_to_search[i] = cmd[i - 2]; + ret = pollForEvent(event_to_search, size + 2, readData, + TIEMOUT_ECHO); + if (ret < OK) { + pr_err("checkEcho: Echo Event not found! ERROR %08X\n", + ret); + return ret | ERROR_CHECK_ECHO_FAIL; + } else if (ret > OK) { + pr_err("checkEcho: Echo Event found but with some error events before! num_error = %d\n", + ret); + return ERROR_CHECK_ECHO_FAIL; + } + + pr_info("ECHO OK!\n"); + return ret; + } +} + + +/** @addtogroup scan_mode + * @{ + */ +/** + * Set a scan mode in the IC + * @param mode scan mode to set; possible values @link scan_opt Scan Mode + * Option @endlink + * @param settings option for the selected scan mode + * (for example @link active_bitmask Active Mode Bitmask @endlink) + * @return OK if success or an error code which specify the type of error + */ +int setScanMode(u8 mode, u8 settings) +{ + u8 cmd[3] = { FTS_CMD_SCAN_MODE, mode, settings }; + int ret, size = 3; + + pr_debug("%s: Setting scan mode: mode = %02X settings = %02X !\n", + __func__, mode, settings); + if (mode == SCAN_MODE_LOW_POWER) + size = 2; + ret = fts_write(cmd, size); + /* use write instead of writeFw because can be called while the + * interrupt are enabled */ + if (ret < OK) { + pr_err("%s: write failed...ERROR %08X !\n", + __func__, ret); + return ret | ERROR_SET_SCAN_MODE_FAIL; + } + pr_debug("%s: Setting scan mode OK!\n", __func__); + return OK; +} +/** @}*/ + + +/** @addtogroup feat_sel + * @{ + */ +/** + * Set a feature and its option in the IC + * @param feat feature to set; possible values @link feat_opt Feature Selection + * Option @endlink + * @param settings pointer to an array of byte which store the options for + * the selected feature (for example the gesture mask to activate + * @link gesture_opt Gesture IDs @endlink) + * @param size in bytes of settings + * @return OK if success or an error code which specify the type of error + */ +int setFeatures(u8 feat, u8 *settings, int size) +{ + u8 cmd[2 + size]; + int i = 0; + int ret; + char buff[(2 + 1) * size + 1]; + int buff_len = sizeof(buff); + int index = 0; + + pr_info("%s: Setting feature: feat = %02X !\n", __func__, feat); + cmd[0] = FTS_CMD_FEATURE; + cmd[1] = feat; + for (i = 0; i < size; i++) { + cmd[2 + i] = settings[i]; + index += scnprintf(buff + index, buff_len - index, + "%02X ", settings[i]); + } + pr_info("%s: Settings = %s\n", __func__, buff); + ret = fts_write(cmd, 2 + size); + /* use write instead of writeFw because can be called while the + * interrupts are enabled */ + if (ret < OK) { + pr_err("%s: write failed...ERROR %08X !\n", __func__, ret); + return ret | ERROR_SET_FEATURE_FAIL; + } + pr_info("%s: Setting feature OK!\n", __func__); + return OK; +} +/** @}*/ + +/** @addtogroup sys_cmd + * @{ + */ +/** + * Write a system command to the IC + * @param sys_cmd System Command to execute; possible values + * @link sys_opt System Command Option @endlink + * @param sett settings option for the selected system command + * (@link sys_special_opt Special Command Option @endlink, @link ito_opt + * ITO Test Option @endlink, @link load_opt Load Host Data Option @endlink) + * @param size in bytes of settings + * @return OK if success or an error code which specify the type of error + */ +int writeSysCmd(u8 sys_cmd, u8 *sett, int size) +{ + u8 cmd[2 + size]; + int ret; + char buff[(2 + 1) * size + 1]; + int buff_len = sizeof(buff); + int index = 0; + + cmd[0] = FTS_CMD_SYSTEM; + cmd[1] = sys_cmd; + + for (ret = 0; ret < size; ret++) { + cmd[2 + ret] = sett[ret]; + index += scnprintf(buff + index, buff_len - index, + "%02X ", sett[ret]); + } + pr_info("%s: Command = %02X %02X %s\n", __func__, cmd[0], + cmd[1], buff); + pr_info("%s: Writing Sys command...\n", __func__); + if (sys_cmd != SYS_CMD_LOAD_DATA) + ret = fts_writeFwCmd(cmd, 2 + size); + else { + if (size >= 1) + ret = requestSyncFrame(sett[0]); + else { + pr_err("%s: No setting argument! ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + } + if (ret < OK) + pr_err("%s: ERROR %08X\n", __func__, ret); + else + pr_info("%s: FINISHED!\n", __func__); + + return ret; +} +/** @}*/ + +/** @addtogroup system_info + * @{ + */ +/** + * Initialize the System Info Struct with default values according to the error + * found during the reading + * @param i2cError 1 if there was an I2C error while reading the System Info + * data from memory, other value if another error occurred + * @return OK if success or an error code which specify the type of error + */ +int defaultSysInfo(int i2cError) +{ + int i; + + pr_info("Setting default System Info...\n"); + + if (i2cError == 1) { + systemInfo.u16_fwVer = 0xFFFF; + systemInfo.u16_cfgProjectId = 0xFFFF; + for (i = 0; i < RELEASE_INFO_SIZE; i++) + systemInfo.u8_releaseInfo[i] = 0xFF; + systemInfo.u16_cxVer = 0xFFFF; + } else { + systemInfo.u16_fwVer = 0x0000; + systemInfo.u16_cfgProjectId = 0x0000; + for (i = 0; i < RELEASE_INFO_SIZE; i++) + systemInfo.u8_releaseInfo[i] = 0x00; + systemInfo.u16_cxVer = 0x0000; + } + + systemInfo.u8_scrRxLen = 0; + systemInfo.u8_scrTxLen = 0; + + pr_info("default System Info DONE!\n"); + return OK; +} + +/** + * Read the System Info data from memory. System Info is loaded automatically + * after every system reset. + * @param request if 1, will be asked to the FW to reload the data, otherwise + * attempt to read it directly from memory + * @return OK if success or an error code which specify the type of error + */ +int readSysInfo(int request) +{ + int ret, i, index = 0; + u8 sett = LOAD_SYS_INFO; + u8 data[SYS_INFO_SIZE] = { 0 }; + char temp[256] = { 0 }; + + if (request == 1) { + pr_info("%s: Requesting System Info...\n", __func__); + + ret = writeSysCmd(SYS_CMD_LOAD_DATA, &sett, 1); + if (ret < OK) { + pr_err("%s: error while writing the sys cmd ERROR %08X\n", + __func__, ret); + goto FAIL; + } + } + + pr_info("%s: Reading System Info...\n", __func__); + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, + ADDR_FRAMEBUFFER, data, SYS_INFO_SIZE, + DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: error while reading the system data ERROR %08X\n", + __func__, ret); + goto FAIL; + } + + pr_info("%s: Parsing System Info...\n", __func__); + + if (data[0] != HEADER_SIGNATURE) { + pr_err("%s: The Header Signature is wrong! sign: %02X != %02X ERROR %08X\n", + __func__, data[0], HEADER_SIGNATURE, + ERROR_WRONG_DATA_SIGN); + ret = ERROR_WRONG_DATA_SIGN; + goto FAIL; + } + + + if (data[1] != LOAD_SYS_INFO) { + pr_err("%s: The Data ID is wrong! ids: %02X != %02X ERROR %08X\n", + __func__, data[3], LOAD_SYS_INFO, + ERROR_DIFF_DATA_TYPE); + ret = ERROR_DIFF_DATA_TYPE; + goto FAIL; + } + + index += 4; + u8ToU16(&data[index], &systemInfo.u16_apiVer_rev); + index += 2; + systemInfo.u8_apiVer_minor = data[index++]; + systemInfo.u8_apiVer_major = data[index++]; + u8ToU16(&data[index], &systemInfo.u16_chip0Ver); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_chip0Id); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_chip1Ver); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_chip1Id); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_fwVer); + index += 2; + pr_info("FW VER = %04X\n", systemInfo.u16_fwVer); + u8ToU16(&data[index], &systemInfo.u16_svnRev); + index += 2; + pr_info("SVN REV = %04X\n", systemInfo.u16_svnRev); + u8ToU16(&data[index], &systemInfo.u16_cfgVer); + index += 2; + pr_info("CONFIG VER = %04X\n", systemInfo.u16_cfgVer); + u8ToU16(&data[index], &systemInfo.u16_cfgProjectId); + index += 2; + pr_info("CONFIG PROJECT ID = %04X\n", systemInfo.u16_cfgProjectId); + u8ToU16(&data[index], &systemInfo.u16_cxVer); + index += 2; + pr_info("CX VER = %04X\n", systemInfo.u16_cxVer); + u8ToU16(&data[index], &systemInfo.u16_cxProjectId); + index += 2; + pr_info("CX PROJECT ID = %04X\n", systemInfo.u16_cxProjectId); + systemInfo.u8_cfgAfeVer = data[index++]; + systemInfo.u8_cxAfeVer = data[index++]; + systemInfo.u8_panelCfgAfeVer = data[index++]; + pr_info("AFE VER: CFG = %02X - CX = %02X - PANEL = %02X\n", + systemInfo.u8_cfgAfeVer, systemInfo.u8_cxAfeVer, + systemInfo.u8_panelCfgAfeVer); + systemInfo.u8_protocol = data[index++]; + pr_info("Protocol = %02X\n", systemInfo.u8_protocol); + /* index+= 1; */ + /* skip reserved area */ + + /* pr_err("Die Info = "); */ + for (i = 0; i < DIE_INFO_SIZE; i++) + systemInfo.u8_dieInfo[i] = data[index++]; + + /* pr_err("\n"); */ + pr_info("%s\n", + printHex("Die Info = ", + systemInfo.u8_dieInfo, + DIE_INFO_SIZE, temp, sizeof(temp))); + memset(temp, 0, 256); + + + /* pr_err("Release Info = "); */ + for (i = 0; i < RELEASE_INFO_SIZE; i++) + systemInfo.u8_releaseInfo[i] = data[index++]; + + /* pr_err("\n"); */ + + pr_info("%s\n", + printHex("Release Info = ", + systemInfo.u8_releaseInfo, + RELEASE_INFO_SIZE, + temp, + sizeof(temp))); + memset(temp, 0, 256); + + u8ToU32(&data[index], &systemInfo.u32_fwCrc); + index += 4; + u8ToU32(&data[index], &systemInfo.u32_cfgCrc); + index += 4; + + index += 16; /* skip reserved area */ + + u8ToU16(&data[index], &systemInfo.u16_scrResX); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_scrResY); + index += 2; + pr_info("Screen Resolution = %d x %d\n", + systemInfo.u16_scrResX, systemInfo.u16_scrResY); + systemInfo.u8_scrTxLen = data[index++]; + pr_info("TX Len = %d\n", systemInfo.u8_scrTxLen); + systemInfo.u8_scrRxLen = data[index++]; + pr_info("RX Len = %d\n", systemInfo.u8_scrRxLen); + systemInfo.u8_keyLen = data[index++]; + pr_info("Key Len = %d\n", systemInfo.u8_keyLen); + systemInfo.u8_forceLen = data[index++]; + pr_info("Force Len = %d\n", systemInfo.u8_forceLen); + + index += 40; /* skip reserved area */ + + u8ToU16(&data[index], &systemInfo.u16_dbgInfoAddr); + index += 2; + + index += 6; /* skip reserved area */ + + u8ToU16(&data[index], &systemInfo.u16_msTchRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_msTchFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_msTchStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_msTchBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_ssTchTxRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssTchTxFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssTchTxStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssTchTxBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_ssTchRxRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssTchRxFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssTchRxStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssTchRxBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_keyRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_keyFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_keyStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_keyBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_frcRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_frcFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_frcStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_frcBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_ssHvrTxRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssHvrTxFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssHvrTxStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssHvrTxBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_ssHvrRxRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssHvrRxFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssHvrRxStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssHvrRxBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_ssPrxTxRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssPrxTxFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssPrxTxStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssPrxTxBaselineAddr); + index += 2; + + u8ToU16(&data[index], &systemInfo.u16_ssPrxRxRawAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssPrxRxFilterAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssPrxRxStrenAddr); + index += 2; + u8ToU16(&data[index], &systemInfo.u16_ssPrxRxBaselineAddr); + index += 2; + + pr_info("Parsed %d bytes!\n", index); + + + if (index != SYS_INFO_SIZE) { + pr_err("%s: index = %d different from %d ERROR %08X\n", + __func__, index, SYS_INFO_SIZE, + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + pr_info("System Info Read DONE!\n"); + return OK; + +FAIL: + defaultSysInfo(isI2cError(ret)); + return ret; +} +/** @}*/ + + +/** + * Read data from the Config Memory + * @param offset Starting address in the Config Memory of data to read + * @param outBuf pointer of a byte array which contain the bytes to read + * @param len number of bytes to read + * @return OK if success or an error code which specify the type of error + */ +int readConfig(u16 offset, u8 *outBuf, int len) +{ + int ret; + u64 final_address = offset + ADDR_CONFIG_OFFSET; + + pr_info("%s: Starting to read config memory at %llx ...\n", + __func__, final_address); + ret = fts_writeReadU8UX(FTS_CMD_CONFIG_R, BITS_16, final_address, + outBuf, len, DUMMY_CONFIG); + if (ret < OK) { + pr_err("%s: Impossible to read Config Memory... ERROR %08X!\n", + __func__, ret); + return ret; + } + + pr_info("%s: Read config memory FINISHED!\n", __func__); + return OK; +} + +/** + * Write data into the Config Memory + * @param offset Starting address in the Config Memory where write the data + * @param data pointer of a byte array which contain the data to write + * @param len number of bytes to write + * @return OK if success or an error code which specify the type of error + */ +int writeConfig(u16 offset, u8 *data, int len) +{ + int ret; + u64 final_address = offset + ADDR_CONFIG_OFFSET; + + pr_info("%s: Starting to write config memory at %llx ...\n", + __func__, final_address); + ret = fts_writeU8UX(FTS_CMD_CONFIG_W, BITS_16, final_address, data, + len); + if (ret < OK) { + pr_err("%s: Impossible to write Config Memory... ERROR %08X!\n", + __func__, ret); + return ret; + } + + pr_info("%s: Write config memory FINISHED!\n", __func__); + return OK; +} + +/** + * Disable the interrupt so the ISR of the driver can not be called + * @return OK if success or an error code which specify the type of error + */ +int fts_disableInterrupt(void) +{ + unsigned long flag; + + if (getClient() != NULL) { + spin_lock_irqsave(&fts_int, flag); + pr_debug("Number of disable = %d\n", disable_irq_count); + if (disable_irq_count == 0) { + pr_debug("Executing Disable...\n"); + disable_irq_nosync(getClient()->irq); + disable_irq_count++; + } + /* disable_irq is re-entrant so it is required to keep track + * of the number of calls of this when reenabling */ + spin_unlock_irqrestore(&fts_int, flag); + pr_debug("Interrupt Disabled!\n"); + return OK; + } else { + pr_err("%s: Impossible get client irq... ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + + +/** + * Disable the interrupt async so the ISR of the driver can not be called + * @return OK if success or an error code which specify the type of error + */ +int fts_disableInterruptNoSync(void) +{ + if (getClient() != NULL) { + spin_lock_irq(&fts_int); + pr_debug("Number of disable = %d\n", disable_irq_count); + if (disable_irq_count == 0) { + pr_debug("Executing Disable...\n"); + disable_irq_nosync(getClient()->irq); + disable_irq_count++; + } + /* disable_irq is re-entrant so it is required to keep track + * of the number of calls of this when reenabling */ + + spin_unlock(&fts_int); + pr_debug("Interrupt No Sync Disabled!\n"); + return OK; + } else { + pr_err("%s: Impossible get client irq... ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Reset the disable_irq count + * @return OK + */ +int fts_resetDisableIrqCount(void) +{ + disable_irq_count = 0; + return OK; +} + +/** + * Enable the interrupt so the ISR of the driver can be called + * @return OK if success or an error code which specify the type of error + */ +int fts_enableInterrupt(void) +{ + unsigned long flag; + + if (getClient() != NULL) { + spin_lock_irqsave(&fts_int, flag); + pr_debug("Number of re-enable = %d\n", disable_irq_count); + while (disable_irq_count > 0) { + /* loop N times according on the pending number of + * disable_irq to truly re-enable the int */ + pr_debug("Executing Enable...\n"); + enable_irq(getClient()->irq); + disable_irq_count--; + } + + spin_unlock_irqrestore(&fts_int, flag); + pr_debug("Interrupt Enabled!\n"); + return OK; + } else { + pr_err("%s: Impossible get client irq... ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Check if there is a crc error in the IC which prevent the fw to run. + * @return OK if no CRC error, or a number >OK according the CRC error found + */ +int fts_crc_check(void) +{ + u8 val; + u8 crc_status; + int res; + u8 error_to_search[6] = { EVT_TYPE_ERROR_CRC_CFG_HEAD, + EVT_TYPE_ERROR_CRC_CFG, + EVT_TYPE_ERROR_CRC_CX, + EVT_TYPE_ERROR_CRC_CX_HEAD, + EVT_TYPE_ERROR_CRC_CX_SUB, + EVT_TYPE_ERROR_CRC_CX_SUB_HEAD }; + + + res = fts_writeReadU8UX(FTS_CMD_HW_REG_R, ADDR_SIZE_HW_REG, ADDR_CRC, + &val, 1, DUMMY_HW_REG); + /* read 2 bytes because the first one is a dummy byte! */ + if (res < OK) { + pr_err("%s Cannot read crc status ERROR %08X\n", __func__, res); + return res; + } + + crc_status = val & CRC_MASK; + if (crc_status != OK) { /* CRC error if crc_status!=0 */ + pr_err("%s CRC ERROR = %02X\n", __func__, crc_status); + return CRC_CODE; + } + + pr_info("%s: Verifying if Config CRC Error...\n", __func__); + res = fts_system_reset(); + if (res >= OK) { + res = pollForErrorType(error_to_search, 2); + if (res < OK) { + pr_info("%s: No Config CRC Error Found!\n", __func__); + pr_info("%s: Verifying if Cx CRC Error...\n", __func__); + res = pollForErrorType(&error_to_search[2], 4); + if (res < OK) { + pr_info("%s: No Cx CRC Error Found!\n", + __func__); + return OK; + } else { + pr_err("%s: Cx CRC Error found! CRC ERROR = %02X\n", + __func__, res); + return CRC_CX; + } + } else { + pr_err("%s: Config CRC Error found! CRC ERROR = %02X\n", + __func__, res); + return CRC_CONFIG; + } + } else { + pr_err("%s: Error while executing system reset! ERROR %08X\n", + __func__, res); + return res; + } + + return OK; +} + +/** + * Request a host data and use the sync method to understand when the FW load + * it + * @param type the type ID of host data to load (@link load_opt Load Host Data + * Option @endlink) + * @return OK if success or an error code which specify the type of error + */ +int requestSyncFrame(u8 type) +{ + u8 request[3] = { FTS_CMD_SYSTEM, SYS_CMD_LOAD_DATA, type }; + u8 readData[DATA_HEADER] = { 0 }; + int ret, retry = 0, retry2 = 0, time_to_count; + int count, new_count; + + pr_info("%s: Starting to get a sync frame...\n", __func__); + + while (retry2 < RETRY_MAX_REQU_DATA) { + pr_info("%s: Reading count...\n", __func__); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, + ADDR_FRAMEBUFFER, readData, DATA_HEADER, + DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: Error while reading count! ERROR %08X\n", + __func__, ret | ERROR_REQU_DATA); + ret |= ERROR_REQU_DATA; + retry2++; + continue; + } + + if (readData[0] != HEADER_SIGNATURE) + pr_err("%s: Invalid Signature while reading count! ERROR %08X\n", + __func__, ret | ERROR_REQU_DATA); + + count = (readData[3] << 8) | readData[2]; + new_count = count; + pr_info("%s: Base count = %d\n", __func__, count); + + pr_info("%s: Requesting frame %02X attempt = %d\n", + __func__, type, retry2 + 1); + ret = fts_write(request, ARRAY_SIZE(request)); + if (ret >= OK) { + pr_info("%s: Polling for new count...\n", __func__); + time_to_count = TIMEOUT_REQU_DATA / TIMEOUT_RESOLUTION; + while (count == new_count && retry < time_to_count) { + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, + BITS_16, + ADDR_FRAMEBUFFER, + readData, + DATA_HEADER, + DUMMY_FRAMEBUFFER); + if ((ret >= OK) && (readData[0] == + HEADER_SIGNATURE) && + (readData[1] == type)) + new_count = ((readData[3] << 8) | + readData[2]); + else + pr_err("%s: invalid Signature or can not read count... ERROR %08X\n", + __func__, ret); + retry++; + mdelay(TIMEOUT_RESOLUTION); + } + + if (count == new_count) { + pr_err("%s: New count not received! ERROR %08X\n", + __func__, + ERROR_TIMEOUT | ERROR_REQU_DATA); + ret = ERROR_TIMEOUT | ERROR_REQU_DATA; + } else { + pr_info("%s: New count found! count = %d! Frame ready!\n", + __func__, new_count); + return OK; + } + } + retry2++; + } + pr_err("%s: Request Data failed! ERROR %08X\n", __func__, ret); + return ret; +} + +/** + * Set the Active Scanning Frequency to a defined value + * @param freq scanning frequency to set in Hz + * @return OK if success or an error code which specify the type of error + * @warning The scan frequency can be set only for the MS scan! + */ +int setActiveScanFrequency(u32 freq) +{ + int res; + u8 temp[2] = { 0 }; + u16 t_cycle; + + pr_info("%s: Setting the scanning frequency to %uHz...\n", + __func__, freq); + + /* read MRN register */ + res = readConfig(ADDR_CONFIG_MRN, temp, 1); + if (res < OK) { + pr_err("%s: error while reading mrn count! ERROR %08X\n", + __func__, res); + return res; + } + + /* setting r count to 0 (= 1 R cycle used) and write it back */ + temp[0] &= (~0x03); + res = writeConfig(ADDR_CONFIG_MRN, temp, 1); + if (res < OK) { + pr_err("%s: error while writing mrn count! ERROR %08X\n", + __func__, res); + return res; + } + + /* set first R cycle slot according the specified frequency */ + /* read T cycle */ + res = readConfig(ADDR_CONFIG_T_CYCLE, temp, 2); + if (res < OK) { + pr_err("%s: error while reading T cycle! ERROR %08X\n", + __func__, res); + return res; + } + t_cycle = ((u16)(temp[1] << 8)) | temp[0]; + + + /* compute the value of R cycle according the formula + * scan_freq = 30Mhz/(2*(T_cycle+R_cycle)) */ + temp[0] = (30000000) / (freq * 2) - t_cycle; + /* write R cycle in Config Area */ + pr_info("%s: T cycle = %d (0x%04X) => R0 cycle = %d (0x%02X)\n", + __func__, t_cycle, t_cycle, temp[0], temp[0]); + res = writeConfig(ADDR_CONFIG_R0_CYCLE, temp, 1); + if (res < OK) { + pr_err("%s: error while writing R0 cycle! ERROR %08X\n", + __func__, res); + return res; + } + + pr_info("%s: Saving Config into the flash ...\n", __func__); + /* save config */ + temp[0] = SAVE_FW_CONF; + res = writeSysCmd(SYS_CMD_SAVE_FLASH, temp, 1); + if (res < OK) { + pr_err("%s: error while saving config into the flash! ERROR %08X\n", + __func__, res); + return res; + } + + /* system reset */ + res = fts_system_reset(); + if (res < OK) { + pr_err("%s: error at system reset! ERROR %08X\n", + __func__, res); + return res; + } + + pr_info("%s: Setting the scanning frequency FINISHED!\n", __func__); + return OK; +} + +/** + * Write Host Data Memory + * @param type type of data to write + * @param data pointer to the data which are written + * @param msForceLen number of force (Tx) channels used with Mutual + * @param msSenseLen number of sense (Rx) channels used with Mutual + * @param ssForceLen number of force (Tx) channel used with Self + * @param ssSenseLen number of sense (Rx) channel used with Self + * @param save if =1 will save the host data written into the flash + * @return OK if success or an error code which specify the type of error + */ +int writeHostDataMemory(u8 type, u8 *data, u8 msForceLen, u8 msSenseLen, + u8 ssForceLen, u8 ssSenseLen, int save) +{ + int res; + int size = (msForceLen * msSenseLen) + (ssForceLen + ssSenseLen); + u8 sett = SPECIAL_WRITE_HOST_MEM_TO_FLASH; + u8 temp[size + SYNCFRAME_DATA_HEADER]; + + memset(temp, 0, size + SYNCFRAME_DATA_HEADER); + pr_info("%s: Starting to write Host Data Memory\n", __func__); + + temp[0] = 0x5A; + temp[1] = type; + temp[5] = msForceLen; + temp[6] = msSenseLen; + temp[7] = ssForceLen; + temp[8] = ssSenseLen; + + memcpy(&temp[16], data, size); + + pr_info("%s: Write Host Data Memory in buffer...\n", __func__); + res = fts_writeU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, + ADDR_FRAMEBUFFER, temp, size + + SYNCFRAME_DATA_HEADER); + + if (res < OK) { + pr_err("%s: error while writing the buffer! ERROR %08X\n", + __func__, res); + return res; + } + + /* save host data memory into the flash */ + if (save == 1) { + pr_info("%s: Trigger writing into the flash...\n", __func__); + res = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1); + if (res < OK) { + pr_err("%s: error while writing into the flash! ERROR %08X\n", + __func__, res); + return res; + } + } + + + pr_info("%s: write Host Data Memory FINISHED!\n", __func__); + return OK; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCore.h b/drivers/input/touchscreen/stm/fts_lib/ftsCore.h new file mode 100644 index 000000000000..ea7608c8fe5c --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsCore.h @@ -0,0 +1,207 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Core definitions ** + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsCore.h + * \brief Contains all the definitions and structs of Core functionalities + */ + +#ifndef FTS_CORE_H +#define FTS_CORE_H + +#include "ftsHardware.h" +#include "ftsSoftware.h" +#include "../fts.h" + +/* HW DATA */ +#define GPIO_NOT_DEFINED -1 /* /< value assumed by reset_gpio when + * the reset pin of the IC is not + * connected */ + + +#define ADDR_SIZE_HW_REG BITS_32 /* /< value of AddrSize for Hw register + * in FTI @see AddrSize */ + +#define DATA_HEADER 4 /* /< size in byte of the header loaded + * with the data in the frambuffer */ + +/** + * Type of CRC errors + */ +typedef enum { + CRC_CODE = 1, /* /< CRC in the code section */ + CRC_CONFIG = 2, /* /< CRC in the config section */ + CRC_CX = 3, /* /< CRC in the cx section */ + CRC_PANEL = 4 /* /< CRC in the panel section */ +} CRC_Error; + +/* CHIP INFO */ +/** @defgroup system_info System Info + * System Info Data collect the most important information about hw and fw + * @{ + */ +/* Size in bytes of System Info data */ +#define SYS_INFO_SIZE 208 /* Num bytes of die info */ +#define DIE_INFO_SIZE 16 /* Num bytes of external release + * in config */ +#define EXTERNAL_RELEASE_INFO_SIZE 8 /* Num bytes of release info in + * sys info + * (first bytes are external + * release) */ +#define RELEASE_INFO_SIZE (EXTERNAL_RELEASE_INFO_SIZE) +/** @}*/ + +/* RETRY MECHANISM */ +#define RETRY_MAX_REQU_DATA 2 /* /< Max number of attempts + * performed + * when requesting data */ +#define RETRY_SYSTEM_RESET 3 /* /< Max number of attempts + * performed + * to reset the IC */ + +/** @addtogroup system_info + * @{ + */ + +/** + * Struct which contains fundamental information about the chip and its + * configuration + */ +typedef struct { + u16 u16_apiVer_rev; /* /< API revision version */ + u8 u8_apiVer_minor; /* /< API minor version */ + u8 u8_apiVer_major; /* /< API major version */ + u16 u16_chip0Ver; /* /< Dev0 version */ + u16 u16_chip0Id; /* /< Dev0 ID */ + u16 u16_chip1Ver; /* /< Dev1 version */ + u16 u16_chip1Id; /* /< Dev1 ID */ + u16 u16_fwVer; /* /< Fw version */ + u16 u16_svnRev; /* /< SVN Revision */ + u16 u16_cfgVer; /* /< Config Version */ + u16 u16_cfgProjectId; /* /< Config Project ID */ + u16 u16_cxVer; /* /< Cx Version */ + u16 u16_cxProjectId; /* /< Cx Project ID */ + u8 u8_cfgAfeVer; /* /< AFE version in Config */ + u8 u8_cxAfeVer; /* /< AFE version in CX */ + u8 u8_panelCfgAfeVer; /* /< AFE version in PanelMem */ + u8 u8_protocol; /* /< Touch Report Protocol */ + u8 u8_dieInfo[DIE_INFO_SIZE]; /* /< Die information */ + u8 u8_releaseInfo[RELEASE_INFO_SIZE]; /* /< Release information */ + u32 u32_fwCrc; /* /< Crc of FW */ + u32 u32_cfgCrc; /* /< Crc of config */ + + u16 u16_scrResX;/* /< X resolution on main screen */ + u16 u16_scrResY;/* /< Y resolution on main screen */ + u8 u8_scrTxLen; /* /< Tx length */ + u8 u8_scrRxLen; /* /< Rx length */ + u8 u8_keyLen; /* /< Key Len */ + u8 u8_forceLen; /* /< Force Len */ + + u16 u16_dbgInfoAddr; /* /< Offset of debug Info structure */ + + u16 u16_msTchRawAddr; /* /< Offset of MS touch raw frame */ + u16 u16_msTchFilterAddr;/* /< Offset of MS touch filter frame */ + u16 u16_msTchStrenAddr; /* /< Offset of MS touch strength frame */ + u16 u16_msTchBaselineAddr; /* /< Offset of MS touch baseline frame + * */ + + u16 u16_ssTchTxRawAddr; /* /< Offset of SS touch force raw frame */ + u16 u16_ssTchTxFilterAddr; /* /< Offset of SS touch force filter + * frame */ + u16 u16_ssTchTxStrenAddr;/* /< Offset of SS touch force strength frame + * */ + u16 u16_ssTchTxBaselineAddr; /* /< Offset of SS touch force baseline + * frame */ + + u16 u16_ssTchRxRawAddr; /* /< Offset of SS touch sense raw frame */ + u16 u16_ssTchRxFilterAddr; /* /< Offset of SS touch sense filter + * frame */ + u16 u16_ssTchRxStrenAddr;/* /< Offset of SS touch sense strength frame + * */ + u16 u16_ssTchRxBaselineAddr; /* /< Offset of SS touch sense baseline + * frame */ + + u16 u16_keyRawAddr; /* /< Offset of key raw frame */ + u16 u16_keyFilterAddr; /* /< Offset of key filter frame */ + u16 u16_keyStrenAddr; /* /< Offset of key strength frame */ + u16 u16_keyBaselineAddr; /* /< Offset of key baseline frame */ + + u16 u16_frcRawAddr; /* /< Offset of force touch raw frame */ + u16 u16_frcFilterAddr; /* /< Offset of force touch filter frame */ + u16 u16_frcStrenAddr; /* /< Offset of force touch strength frame */ + u16 u16_frcBaselineAddr;/* /< Offset of force touch baseline frame */ + + u16 u16_ssHvrTxRawAddr; /* /< Offset of SS hover Force raw frame */ + u16 u16_ssHvrTxFilterAddr; /* /< Offset of SS hover Force filter + * frame */ + u16 u16_ssHvrTxStrenAddr;/* /< Offset of SS hover Force strength frame + * */ + u16 u16_ssHvrTxBaselineAddr; /* /< Offset of SS hover Force baseline + * frame */ + + u16 u16_ssHvrRxRawAddr; /* /< Offset of SS hover Sense raw frame */ + u16 u16_ssHvrRxFilterAddr; /* /< Offset of SS hover Sense filter + * frame */ + u16 u16_ssHvrRxStrenAddr; /* /< Offset of SS hover Sense strength + * frame */ + u16 u16_ssHvrRxBaselineAddr; /* /< Offset of SS hover Sense baseline + * frame */ + + u16 u16_ssPrxTxRawAddr; /* /< Offset of SS proximity force raw frame */ + u16 u16_ssPrxTxFilterAddr; /* /< Offset of SS proximity force + * filter frame */ + u16 u16_ssPrxTxStrenAddr;/* /< Offset of SS proximity force strength + * frame */ + u16 u16_ssPrxTxBaselineAddr; /* /< Offset of SS proximity force + * baseline frame */ + + u16 u16_ssPrxRxRawAddr; /* /< Offset of SS proximity sense raw frame */ + u16 u16_ssPrxRxFilterAddr; /* /< Offset of SS proximity sense + * filter frame */ + u16 u16_ssPrxRxStrenAddr;/* /< Offset of SS proximity sense strength + * frame */ + u16 u16_ssPrxRxBaselineAddr; /* /< Offset of SS proximity sense + * baseline frame */ +} SysInfo; + +/** @}*/ + +int initCore(struct fts_ts_info *info); +void setResetGpio(int gpio); +int fts_system_reset(void); +int isSystemResettedUp(void); +int isSystemResettedDown(void); +void setSystemResetedUp(int val); +void setSystemResetedDown(int val); +int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int + time_to_wait); +int checkEcho(u8 *cmd, int size); +int setScanMode(u8 mode, u8 settings); +int setFeatures(u8 feat, u8 *settings, int size); +int defaultSysInfo(int i2cError); +int writeSysCmd(u8 sys_cmd, u8 *sett, int size); +int readSysInfo(int request); +int readConfig(u16 offset, u8 *outBuf, int len); +int writeConfig(u16 offset, u8 *data, int len); +int fts_disableInterrupt(void); +int fts_disableInterruptNoSync(void); +int fts_resetDisableIrqCount(void); +int fts_enableInterrupt(void); +int fts_crc_check(void); +int requestSyncFrame(u8 type); +int setActiveScanFrequency(u32 freq); +int writeHostDataMemory(u8 type, u8 *data, u8 msForceLen, u8 msSenseLen, + u8 ssForceLen, u8 ssSenseLen, int save); +#endif /* FTS_CORE_H */ diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsError.c b/drivers/input/touchscreen/stm/fts_lib/ftsError.c new file mode 100644 index 000000000000..2ae433715bff --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsError.c @@ -0,0 +1,349 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS error/info kernel log reporting * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsError.c + * \brief Contains all the function which handle with Error conditions + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/delay.h> + + +#include "../fts.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsIO.h" +#include "ftsTool.h" +#include "ftsCompensation.h" + + +static ErrorList errors;/* /< private variable which implement the Error List */ + +/** + * Check if an error code is related to an I2C failure + * @param error error code to check + * @return 1 if the first level error code is I2C related otherwise 0 + */ +int isI2cError(int error) +{ + if (((error & 0x000000FF) >= (ERROR_BUS_R & 0x000000FF)) && + ((error & 0x000000FF) <= (ERROR_BUS_O & 0x000000FF))) + return 1; + else + return 0; +} + + +/** + * Dump in the kernel log some debug info in case of FW hang + * @param outBuf (optional)pointer to bytes array where to copy the debug info, + * if NULL the data will just printed on the kernel log + * @param size dimension in bytes of outBuf, + * if > ERROR_DUMP_ROW_SIZE*ERROR_DUMP_COL_SIZE, only the first + * ERROR_DUMP_ROW_SIZE*ERROR_DUMP_COL_SIZE bytes will be copied + * @return OK if success or an error code which specify the type of error + */ +int dumpErrorInfo(u8 *outBuf, int size) +{ + int ret, i; + u8 data[ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE] = { 0 }; + u32 sign = 0; + + pr_err("%s: Starting dump of error info...\n", __func__); + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, ADDR_ERROR_DUMP, + data, ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE, + DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("%s: reading data ERROR %08X\n", __func__, + ret); + return ret; + } else { + int buff_len, index = 0; + char *buff; + + buff_len = (2 + 1) * ERROR_DUMP_COL_SIZE + 1; + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return -ENOMEM; + } + + if (outBuf != NULL) { + sign = size > ERROR_DUMP_ROW_SIZE * + ERROR_DUMP_COL_SIZE ? ERROR_DUMP_ROW_SIZE * + ERROR_DUMP_COL_SIZE : size; + memcpy(outBuf, data, sign); + pr_err("%s: error info copied in the buffer!\n", + __func__); + } + pr_err("%s: Error Info =\n", __func__); + u8ToU32(data, &sign); + if (sign != ERROR_DUMP_SIGNATURE) + pr_err("%s: Wrong Error Signature! Data may be invalid!\n", + __func__); + else + pr_err("%s: Error Signature OK! Data are valid!\n", + __func__); + + for (i = 0; i < ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE; + i++) { + index += scnprintf(buff + index, buff_len - index, + "%02X ", data[i]); + if (i % ERROR_DUMP_COL_SIZE == + (ERROR_DUMP_COL_SIZE - 1)) { + pr_err("%s: %d) %s\n", __func__, + i / ERROR_DUMP_COL_SIZE, + buff); + index = 0; + } + } + + kfree(buff); + pr_err("%s: dump of error info FINISHED!\n", __func__); + return OK; + } +} + + +/** + * Implement recovery strategies to be used when an error event is found + * while polling the FIFO + * @param event error event found during the polling + * @param size size of event + * @return OK if the error event doesn't require any action or the recovery + * strategy doesn't have any impact in the possible procedure that trigger the + * error, + * otherwise return an error code which specify the kind of error. + * If ERROR_HANDLER_STOP_PROC the calling function must stop! + */ +int errorHandler(u8 *event, int size) +{ + int res = OK; + struct fts_ts_info *info = NULL; + + if (getDev() != NULL) + info = dev_get_drvdata(getDev()); + + if (info != NULL && event != NULL && size > 1 && + event[0] == EVT_ID_ERROR) { + pr_debug("errorHandler: Starting handling...\n"); + addErrorIntoList(event, size); + switch (event[1]) { /* TODO: write an error log for + * undefined command subtype 0xBA */ + case EVT_TYPE_ERROR_ESD: /* esd */ + res = fts_chip_powercycle(info); + if (res < OK) + pr_err("errorHandler: Error performing powercycle ERROR %08X\n", + res); + + res = fts_system_reset(); + if (res < OK) + pr_err("errorHandler: Cannot reset the device ERROR %08X\n", + res); + res = (ERROR_HANDLER_STOP_PROC | res); + break; + + case EVT_TYPE_ERROR_WATCHDOG: /* watchdog */ + dumpErrorInfo(NULL, 0); + res = fts_system_reset(); + if (res < OK) + pr_err("errorHandler: Cannot reset the device ERROR %08X\n", + res); + res = (ERROR_HANDLER_STOP_PROC | res); + break; + + case EVT_TYPE_ERROR_ITO_FORCETOGND: + pr_err("errorHandler: Force Short to GND!\n"); + break; + case EVT_TYPE_ERROR_ITO_SENSETOGND: + pr_err("errorHandler: Sense short to GND!\n"); + break; + case EVT_TYPE_ERROR_ITO_FORCETOVDD: + pr_err("errorHandler: Force short to VDD!\n"); + break; + case EVT_TYPE_ERROR_ITO_SENSETOVDD: + pr_err("errorHandler: Sense short to VDD!\n"); + break; + case EVT_TYPE_ERROR_ITO_FORCE_P2P: + pr_err("errorHandler: Force Pin to Pin Short!\n"); + break; + case EVT_TYPE_ERROR_ITO_SENSE_P2P: + pr_err("errorHandler: Sense Pin to Pin Short!\n"); + break; + case EVT_TYPE_ERROR_ITO_FORCEOPEN: + pr_err("errorHandler: Force Open !\n"); + break; + case EVT_TYPE_ERROR_ITO_SENSEOPEN: + pr_err("errorHandler: Sense Open !\n"); + break; + case EVT_TYPE_ERROR_ITO_KEYOPEN: + pr_err("errorHandler: Key Open !\n"); + break; + + case EVT_TYPE_ERROR_FLASH_FAILED: + pr_err("errorHandler: Previous flash failed!\n"); + info->reflash_fw = 1; + break; + + default: + pr_debug("errorHandler: No Action taken!\n"); + break; + } + pr_debug("errorHandler: handling Finished! res = %08X\n", + res); + return res; + } else { + pr_err("errorHandler: event Null or not correct size! ERROR %08X\n", + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + + +/** + * Add an error event into the Error List + * @param event error event to add + * @param size size of event + * @return OK + */ +int addErrorIntoList(u8 *event, int size) +{ + int i = 0; + + pr_debug("Adding error in to ErrorList...\n"); + + memcpy(&errors.list[errors.last_index * FIFO_EVENT_SIZE], event, size); + i = FIFO_EVENT_SIZE - size; + if (i > 0) { + pr_info("Filling last %d bytes of the event with zero...\n", i); + memset(&errors.list[errors.last_index * FIFO_EVENT_SIZE + size], + 0, i); + } + pr_debug("Adding error in to ErrorList... FINISHED!\n"); + + errors.count += 1; + if (errors.count > FIFO_DEPTH) + pr_err("ErrorList is going in overflow... the first %d event(s) were override!\n", + errors.count - FIFO_DEPTH); + errors.last_index = (errors.last_index + 1) % FIFO_DEPTH; + + return OK; +} + +/** + * Reset the Error List setting the count and last_index to 0. + * @return OK + */ +int resetErrorList(void) +{ + errors.count = 0; + errors.last_index = 0; + memset(errors.list, 0, FIFO_DEPTH * FIFO_EVENT_SIZE); + /* if count is not considered is better reset also the list in order to + * avoid to read data previously copied into the list */ + return OK; +} + +/** + * Get the number of error events copied into the Error List + * @return the number of error events into the Error List + */ +int getErrorListCount(void) +{ + if (errors.count > FIFO_DEPTH) + return FIFO_DEPTH; + else + return errors.count; +} + +/* in case of success return the index of the event found */ +/** + * Scroll the Error List looking for the event specified + * @param event_to_search event_to_search pointer to an array of int where + * each element correspond to a byte of the event to find. If the element + * of the array has value -1, the byte of the event, in the same position + * of the element is ignored. + * @param event_bytes size of event_to_search + * @return a value >=0 if the event is found which represent the index of + * the Error List where the event is located otherwise an error code + */ +int pollErrorList(int *event_to_search, int event_bytes) +{ + int i = 0, j = 0, find = 0; + int count = getErrorListCount(); + + pr_debug("Starting to poll ErrorList...\n"); + while (find != 1 && i < count) { + find = 1; + for (j = 0; j < event_bytes; j++) { + if ((event_to_search[i] != -1) && + ((int)errors.list[i * FIFO_EVENT_SIZE + j] != + event_to_search[i])) { + find = 0; + break; + } + } + i++; + } + if (find == 1) { + pr_debug("Error Found into ErrorList!\n"); + return i - 1; /* there is i++ at the end of the while */ + } else { + pr_err("Error Not Found into ErrorList! ERROR %08X\n", + ERROR_TIMEOUT); + return ERROR_TIMEOUT; + } +} + + + +/** + * Poll the Error List looking for any error types passed in the arguments. + * Return at the first match! + * @param list pointer to a list of error types to look for + * @param size size of list + * @return error type found if success or ERROR_TIMEOUT + */ +int pollForErrorType(u8 *list, int size) +{ + int i = 0, j = 0, find = 0; + int count = getErrorListCount(); + + pr_info("%s: Starting to poll ErrorList... count = %d\n", + __func__, count); + while (find != 1 && i < count) { + for (j = 0; j < size; j++) { + if (list[j] == errors.list[i * FIFO_EVENT_SIZE + 1]) { + find = 1; + break; + } + } + i++; + } + if (find == 1) { + pr_info("%s: Error Type %02X into ErrorList!\n", + __func__, list[j]); + return list[j]; + } else { + pr_err("%s: Error Type Not Found into ErrorList! ERROR %08X\n", + __func__, ERROR_TIMEOUT); + return ERROR_TIMEOUT; + } +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsError.h b/drivers/input/touchscreen/stm/fts_lib/ftsError.h new file mode 100644 index 000000000000..f12d9eed88cb --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsError.h @@ -0,0 +1,231 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS error/info kernel log reporting * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsError.h + * \brief Contains all the definitions and structs which refer to Error + * conditions + */ + +#ifndef FTS_ERROR_H +#define FTS_ERROR_H + +#include "ftsHardware.h" +#include "ftsSoftware.h" + + +/** @defgroup error_codes Error Codes + * Error codes that can be reported by the driver functions. + * An error code is made up by 4 bytes, each byte indicate a logic error + * level.\n + * From the LSB to the MSB, the logic level increase going from a low level + * error (I2C,TIMEOUT) to an high level error (flashing procedure fail, + * production test fail etc) + * @{ + */ + +/* FIRST LEVEL ERROR CODE */ +/** @defgroup first_level First Level Error Code + * @ingroup error_codes + * Errors related to low level operation which are not under control of driver, + * such as: communication protocol (I2C/SPI), timeout, file operations ... + * @{ + */ +#define OK (0x00000000) /* /< No ERROR */ +#define ERROR_ALLOC (0x80000001) /* /< allocation of memory + * failed */ +#define ERROR_BUS_R (0x80000002) /* /< i2c/spi read failed */ +#define ERROR_BUS_W (0x80000003) /* /< i2c/spi write failed */ +#define ERROR_BUS_WR (0x80000004) /* /< i2c/spi write/read + * failed */ +#define ERROR_BUS_O (0x80000005) /* /< error during + * opening an i2c device */ +#define ERROR_OP_NOT_ALLOW (0x80000006) /* /< operation not allowed */ +#define ERROR_TIMEOUT (0x80000007) /* /< timeout expired! + * exceed the max number + * of retries or the max + * waiting time */ +#define ERROR_FILE_NOT_FOUND (0x80000008) /* /< the file that i + * want to open is not found */ +#define ERROR_FILE_PARSE (0x80000009) /* /< error during parsing + * the file */ +#define ERROR_FILE_READ (0x8000000A) /* /< error during + * reading the file */ +#define ERROR_LABEL_NOT_FOUND (0x8000000B) /* /< label not found */ +#define ERROR_FW_NO_UPDATE (0x8000000C) /* /< fw in the chip + * newer than the one in + * the memmh */ +#define ERROR_FLASH_UNKNOWN (0x8000000D) /* /< flash status busy + * or unknown */ +/** @}*/ + +/* SECOND LEVEL ERROR CODE */ +/** @defgroup second_level Second Level Error Code + * @ingroup error_codes + * Errors related to simple logic operations in the IC which require one + * command or which are part of a more complex procedure + * @{ + */ +#define ERROR_DISABLE_INTER (0x80000200) /* /< unable to + * disable the + * interrupt */ +#define ERROR_ENABLE_INTER (0x80000300) /* /< unable to activate + * the interrupt */ +#define ERROR_READ_CONFIG (0x80000400) /* /< failed to read + * config memory */ +#define ERROR_GET_OFFSET (0x80000500) /* /< unable to + * read an offset from + * memory */ +#define ERROR_GET_FRAME_DATA (0x80000600) /* /< unable to + * retrieve the data of + * a required frame */ +#define ERROR_DIFF_DATA_TYPE (0x80000700) /* /< FW answers + * with an event that + * has a different + * address respect the + * request done */ +#define ERROR_WRONG_DATA_SIGN (0x80000800) /* /< the signature of + * the host data is not + * HEADER_SIGNATURE */ +#define ERROR_SET_SCAN_MODE_FAIL (0x80000900) /* /< setting + * the scanning mode + * failed + * (sense on/off + * etc...) */ +#define ERROR_SET_FEATURE_FAIL (0x80000A00) /* /< setting a specific + * feature failed */ +#define ERROR_SYSTEM_RESET_FAIL (0x80000B00) /* /< the command + * SYSTEM RESET + * failed */ +#define ERROR_FLASH_NOT_READY (0x80000C00) /* /< flash status not + * ready within a + * timeout */ +#define ERROR_FW_VER_READ (0x80000D00) /* /< unable to retrieve + * fw_vers or the + * config_id */ +#define ERROR_GESTURE_ENABLE_FAIL (0x80000E00) /* /< unable to + * enable/disable + * the gesture */ +#define ERROR_GESTURE_START_ADD (0x80000F00) /* /< unable to start to + * add custom gesture */ +#define ERROR_GESTURE_FINISH_ADD (0x80001000) /* /< unable to finish + * to add custom gesture + */ +#define ERROR_GESTURE_DATA_ADD (0x80001100) /* /< unable to add + * custom gesture data + * */ +#define ERROR_GESTURE_REMOVE (0x80001200) /* /< unable to remove + * custom gesture data + * */ +#define ERROR_FEATURE_ENABLE_DISABLE (0x80001300) /* /< unable to + * enable/disable a + * feature mode in + * the IC */ +#define ERROR_NOISE_PARAMETERS (0x80001400) /* /< unable to set/read + * noise parameter in + * the IC */ +#define ERROR_CH_LEN (0x80001500) /* /< unable to retrieve + * the force and/or + * sense length */ +/** @}*/ + +/* THIRD LEVEL ERROR CODE */ +/** @defgroup third_level Third Level Error Code + * @ingroup error_codes + * Errors related to logic operations in the IC which require more + * commands/steps or which are part of a more complex procedure + * @{ + */ +#define ERROR_REQU_COMP_DATA (0x80010000) /* /< compensation data + * request failed */ +#define ERROR_REQU_DATA (0x80020000) /* /< data request + * failed */ +#define ERROR_COMP_DATA_HEADER (0x80030000) /* /< unable to retrieve + * the compensation data + * header */ +#define ERROR_COMP_DATA_GLOBAL (0x80040000) /* /< unable to retrieve + * the global + * compensation data */ +#define ERROR_COMP_DATA_NODE (0x80050000) /* /< unable to retrieve + * the compensation data + * for each node */ +#define ERROR_TEST_CHECK_FAIL (0x80060000) /* /< check of + * production limits or + * of fw answers failed */ +#define ERROR_MEMH_READ (0x80070000) /* /< memh reading + * failed */ +#define ERROR_FLASH_BURN_FAILED (0x80080000) /* /< flash burn failed */ +#define ERROR_MS_TUNING (0x80090000) /* /< ms tuning failed */ +#define ERROR_SS_TUNING (0x800A0000) /* /< ss tuning failed */ +#define ERROR_LP_TIMER_TUNING (0x800B0000) /* /< lp timer + * calibration failed */ +#define ERROR_SAVE_CX_TUNING (0x800C0000) /* /< save cx data to + * flash failed */ +#define ERROR_HANDLER_STOP_PROC (0x800D0000) /* /< stop the poll of the FIFO + * if particular errors are + * found */ +#define ERROR_CHECK_ECHO_FAIL (0x800E0000) /* /< unable to retrieve + * echo event */ +#define ERROR_GET_FRAME (0x800F0000) /* /< unable to get frame */ +/** @}*/ + +/* FOURTH LEVEL ERROR CODE */ +/** @defgroup fourth_level Fourth Level Error Code + * @ingroup error_codes + * Errors related to the highest logic operations in the IC which have an + * important impact on the driver flow or which require several commands and + * steps to be executed + * @{ + */ +#define ERROR_PROD_TEST_DATA (0x81000000) /* /< production data + * test failed */ +#define ERROR_FLASH_PROCEDURE (0x82000000) /* /< fw update + * procedure failed */ +#define ERROR_PROD_TEST_ITO (0x83000000) /* /< production + * ito test failed */ +#define ERROR_PROD_TEST_INITIALIZATION (0x84000000) /* /< production + * initialization + * test failed */ +#define ERROR_GET_INIT_STATUS (0x85000000) /* /< mismatch of the MS or + * SS tuning_version */ +/** @}*/ + +/** @}*/ /* end of error_commands section */ + +/** + * Struct which store an ordered list of the errors events encountered during + *the polling of a FIFO. + * The max number of error events that can be stored is equal to FIFO_DEPTH + */ +typedef struct { + u8 list[FIFO_DEPTH * FIFO_EVENT_SIZE]; /* /< byte array which contains + * the series of error events + * encountered from the last + * reset of the list. */ + int count; /* /< number of error events stored in the list */ + int last_index; /* /< index of the list where will be stored the next + * error event. Subtract -1 to have the index of the + * last error event! */ +} ErrorList; + +int isI2cError(int error); +int dumpErrorInfo(u8 *outBuf, int size); +int errorHandler(u8 *event, int size); +int addErrorIntoList(u8 *event, int size); +int getErrorListCount(void); +int resetErrorList(void); +int pollErrorList(int *event_to_search, int event_bytes); +int pollForErrorType(u8 *list, int size); +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFlash.c b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.c new file mode 100644 index 000000000000..724588955dd3 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.c @@ -0,0 +1,991 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS API for Flashing the IC * + * * + ************************************************************************** + ************************************************************************** + * + */ + + +/*! + * \file ftsFlash.c + * \brief Contains all the functions to handle the FW update process + */ + +#include "ftsCore.h" +#include "ftsCompensation.h" +#include "ftsError.h" +#include "ftsFlash.h" +#include "ftsFrame.h" +#include "ftsIO.h" +#include "ftsSoftware.h" +#include "ftsTest.h" +#include "ftsTime.h" +#include "ftsTool.h" +#include "../fts.h" /* needed for including the define FW_H_FILE */ + + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/serio.h> +#include <linux/time.h> +#include <linux/delay.h> +#include <linux/ctype.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/firmware.h> + + +#ifdef FW_H_FILE +#include "../fts_fw.h" +#endif + + +extern SysInfo systemInfo; /* /< forward declaration of the global variable + * of containing System Info Data */ + + +/** + * Retrieve the actual FW data from the system (bin file or header file) + * @param pathToFile name of FW file to load or "NULL" if the FW data should be + * loaded by a .h file + * @param data pointer to the pointer which will contains the FW data + * @param size pointer to a variable which will contain the size of the loaded + * data + * @return OK if success or an error code which specify the type of error + */ +int getFWdata(const char *pathToFile, u8 **data, int *size) +{ + const struct firmware *fw = NULL; + struct device *dev = getDev(); + struct fts_ts_info *info = NULL; + int res, from = 0; + char *path = (char *)pathToFile; + + if (dev != NULL) + info = dev_get_drvdata(dev); + + pr_info("getFWdata starting ...\n"); + if (strncmp(pathToFile, "NULL", 4) == 0) { + from = 1; + if (info != NULL && info->board->fw_name) + path = (char *)info->board->fw_name; + else + path = PATH_FILE_FW; + } + /* keep the switch case because if the argument passed is null but + * the option from .h is not set we still try to load from bin */ + switch (from) { +#ifdef FW_H_FILE + case 1: + pr_info("Read FW from .h file!\n"); + *size = FW_SIZE_NAME; + *data = (u8 *)kmalloc((*size) * sizeof(u8), GFP_KERNEL); + if (*data == NULL) { + pr_err("getFWdata: Impossible to allocate memory! ERROR %08X\n", + ERROR_ALLOC); + return ERROR_ALLOC; + } + memcpy(*data, (u8 *)FW_ARRAY_NAME, (*size)); + + break; +#endif + default: + pr_info("Read FW from BIN file %s !\n", path); + + if (dev != NULL) { + res = request_firmware(&fw, path, dev); + if (res == 0) { + *size = fw->size; + *data = (u8 *)kmalloc((*size) * sizeof(u8), + GFP_KERNEL); + if (*data == NULL) { + pr_err("getFWdata: Impossible to allocate memory! ERROR %08X\n", + ERROR_ALLOC); + release_firmware(fw); + return ERROR_ALLOC; + } + memcpy(*data, (u8 *)fw->data, (*size)); + release_firmware(fw); + } else { + pr_err("getFWdata: No File found! ERROR %08X\n", + ERROR_FILE_NOT_FOUND); + return ERROR_FILE_NOT_FOUND; + } + } else { + pr_err("getFWdata: No device found! ERROR %08X\n", + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + } + + pr_info("getFWdata Finished!\n"); + return OK; +} + + +/** + * Perform all the steps to read the FW that should be burnt in the IC from + * the system and parse it in order to fill a Firmware struct with the relevant + * info + * @param path name of FW file to load or "NULL" if the FW data should be + * loaded by a .h file + * @param fw pointer to a Firmware variable which will contains the FW data and + * info + * @param keep_cx if 1, the CX area will be loaded otherwise will be skipped + * @return OK if success or an error code which specify the type of error + */ +int readFwFile(const char *path, Firmware *fw, int keep_cx) +{ + int res; + int orig_size; + u8 *orig_data = NULL; + + + res = getFWdata(path, &orig_data, &orig_size); + if (res < OK) { + pr_err("readFwFile: impossible retrieve FW... ERROR %08X\n", + ERROR_MEMH_READ); + return res | ERROR_MEMH_READ; + } + res = parseBinFile(orig_data, orig_size, fw, keep_cx); + if (res < OK) { + pr_err("readFwFile: impossible parse ERROR %08X\n", + ERROR_MEMH_READ); + return res | ERROR_MEMH_READ; + } + + return OK; +} + +/** + * Perform all the steps necessary to burn the FW into the IC + * @param path name of FW file to load or "NULL" if the FW data should be + * loaded by a .h file + * @param force if 1, the flashing procedure will be forced and executed + * regardless the additional info, otherwise the FW in the file will be burnt + * only if it is newer than the one running in the IC + * @param keep_cx if 1, the CX area will be loaded and burnt otherwise will be + * skipped and the area will be untouched + * @return OK if success or an error code which specify the type of error + */ +int flashProcedure(const char *path, int force, int keep_cx) +{ + Firmware fw; + int res; + + fw.data = NULL; + pr_info("Reading Fw file...\n"); + res = readFwFile(path, &fw, keep_cx); + if (res < OK) { + pr_err("flashProcedure: ERROR %08X\n", + (res | ERROR_FLASH_PROCEDURE)); + kfree(fw.data); + return res | ERROR_FLASH_PROCEDURE; + } + pr_info("Fw file read COMPLETED!\n"); + + pr_info("Starting flashing procedure...\n"); + res = flash_burn(fw, force, keep_cx); + if (res < OK && res != (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED)) { + pr_err("flashProcedure: ERROR %08X\n", + ERROR_FLASH_PROCEDURE); + kfree(fw.data); + return res | ERROR_FLASH_PROCEDURE; + } + pr_info("flashing procedure Finished!\n"); + kfree(fw.data); + + return res; +} + +/** + * Poll the Flash Status Registers after the execution of a command to check + * if the Flash becomes ready within a timeout + * @param type register to check according to the previous command sent + * @return OK if success or an error code which specify the type of error + */ +int wait_for_flash_ready(u8 type) +{ + u8 cmd[5] = { FTS_CMD_HW_REG_R, 0x20, 0x00, 0x00, type }; + + u8 readData[2] = { 0 }; + int i, res = -1; + + pr_info("Waiting for flash ready ...\n"); + for (i = 0; i < FLASH_RETRY_COUNT && res != 0; i++) { + res = fts_writeRead(cmd, ARRAY_SIZE(cmd), readData, 2); + if (res < OK) + pr_err("wait_for_flash_ready: ERROR %08X\n", + ERROR_BUS_W); + else { +#ifdef I2C_INTERFACE /* in case of spi there is a dummy byte */ + res = readData[0] & 0x80; +#else + res = readData[1] & 0x80; +#endif + + pr_info("flash status = %d\n", res); + } + mdelay(FLASH_WAIT_BEFORE_RETRY); + } + + if (i == FLASH_RETRY_COUNT && res != 0) { + pr_err("Wait for flash TIMEOUT! ERROR %08X\n", + ERROR_TIMEOUT); + return ERROR_TIMEOUT; + } + + pr_info("Flash READY!\n"); + return OK; +} + + +/** + * Put the M3 in hold + * @return OK if success or an error code which specify the type of error + */ +int hold_m3(void) +{ + int ret; + u8 cmd[1] = { 0x01 }; + + pr_info("Command m3 hold...\n"); + ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, + ADDR_SYSTEM_RESET, cmd, 1); + if (ret < OK) { + pr_err("hold_m3: ERROR %08X\n", ret); + return ret; + } + pr_info("Hold M3 DONE!\n"); + +#if !defined(I2C_INTERFACE) && defined(SPI4_WIRE) + /* configure manually SPI4 because when no fw is running the chip use + * SPI3 by default */ + pr_info("Setting SPI4 mode...\n"); + cmd[0] = 0x10; + ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, + ADDR_GPIO_DIRECTION, cmd, 1); + if (ret < OK) { + pr_err("hold_m3: can not set gpio dir ERROR %08X\n", ret); + return ret; + } + + cmd[0] = 0x02; + ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, + ADDR_GPIO_PULLUP, cmd, 1); + if (ret < OK) { + pr_err("hold_m3: can not set gpio pull-up ERROR %08X\n", ret); + return ret; + } + + cmd[0] = 0x07; + ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, + ADDR_GPIO_CONFIG_REG2, cmd, 1); + if (ret < OK) { + pr_err("hold_m3: can not set gpio config ERROR %08X\n", ret); + return ret; + } + + cmd[0] = 0x30; + ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, + ADDR_GPIO_CONFIG_REG0, cmd, 1); + if (ret < OK) { + pr_err("hold_m3: can not set gpio config ERROR %08X\n", ret); + return ret; + } + + cmd[0] = SPI4_MASK; + ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, ADDR_ICR, cmd, + 1); + if (ret < OK) { + pr_err("hold_m3: can not set spi4 mode ERROR %08X\n", ret); + return ret; + } + mdelay(1); /* wait for the GPIO to stabilize */ +#endif + + return OK; +} + + + + +/** + * Parse the raw data read from a FW file in order to fill properly the fields + * of a Firmware variable + * @param fw_data raw FW data loaded from system + * @param fw_size size of fw_data + * @param fwData pointer to a Firmware variable which will contain the + * processed data + * @param keep_cx if 1, the CX area will be loaded and burnt otherwise will be + * skipped and the area will be untouched + * @return OK if success or an error code which specify the type of error + */ +int parseBinFile(u8 *fw_data, int fw_size, Firmware *fwData, int keep_cx) +{ + int dimension, index = 0; + u32 temp; + int res, i; + char buff[(2 + 1) * EXTERNAL_RELEASE_INFO_SIZE + 1]; + int buff_len = sizeof(buff); + int buff_index = 0; + + /* the file should contain at least the header plus the content_crc */ + if (fw_size < FW_HEADER_SIZE + FW_BYTES_ALIGN || fw_data == NULL) { + pr_err("parseBinFile: Read only %d instead of %d... ERROR %08X\n", + fw_size, FW_HEADER_SIZE + FW_BYTES_ALIGN, + ERROR_FILE_PARSE); + res = ERROR_FILE_PARSE; + goto END; + } else { + /* start parsing of bytes */ + u8ToU32(&fw_data[index], &temp); + if (temp != FW_HEADER_SIGNATURE) { + pr_err("parseBinFile: Wrong Signature %08X ... ERROR %08X\n", + temp, ERROR_FILE_PARSE); + res = ERROR_FILE_PARSE; + goto END; + } + pr_info("parseBinFile: Fw Signature OK!\n"); + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + if (temp != FW_FTB_VER) { + pr_err("parseBinFile: Wrong ftb_version %08X ... ERROR %08X\n", + temp, ERROR_FILE_PARSE); + res = ERROR_FILE_PARSE; + goto END; + } + pr_info("parseBinFile: ftb_version OK!\n"); + index += FW_BYTES_ALIGN; + if (fw_data[index] != DCHIP_ID_0 || fw_data[index + 1] != + DCHIP_ID_1) { + pr_err("parseBinFile: Wrong target %02X != %02X %02X != %02X ... ERROR %08X\n", + fw_data[index], DCHIP_ID_0, + fw_data[index + 1], + DCHIP_ID_1, ERROR_FILE_PARSE); + res = ERROR_FILE_PARSE; + goto END; + } + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + pr_info("parseBinFile: FILE SVN REV = %08X\n", temp); + + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + fwData->fw_ver = temp; + pr_info("parseBinFile: FILE Fw Version = %04X\n", + fwData->fw_ver); + + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + pr_info("parseBinFile: FILE Config Project ID = %08X\n", temp); + + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + fwData->config_ver = temp; + pr_info("parseBinFile: FILE Config Version = %08X\n", + fwData->config_ver); + + index += FW_BYTES_ALIGN * 2; /* skip reserved data */ + + index += FW_BYTES_ALIGN; + for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) { + fwData->externalRelease[i] = fw_data[index++]; + buff_index += scnprintf(buff + buff_index, + buff_len - buff_index, + "%02X ", + fwData->externalRelease[i]); + } + pr_info("parseBinFile: File External Release = %s\n", buff); + + /* index+=FW_BYTES_ALIGN; */ + u8ToU32(&fw_data[index], &temp); + fwData->sec0_size = temp; + pr_info("parseBinFile: sec0_size = %08X (%d bytes)\n", + fwData->sec0_size, fwData->sec0_size); + + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + fwData->sec1_size = temp; + pr_info("parseBinFile: sec1_size = %08X (%d bytes)\n", + fwData->sec1_size, fwData->sec1_size); + + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + fwData->sec2_size = temp; + pr_info("parseBinFile: sec2_size = %08X (%d bytes)\n", + fwData->sec2_size, fwData->sec2_size); + + index += FW_BYTES_ALIGN; + u8ToU32(&fw_data[index], &temp); + fwData->sec3_size = temp; + pr_info("parseBinFile: sec3_size = %08X (%d bytes)\n", + fwData->sec3_size, fwData->sec3_size); + + index += FW_BYTES_ALIGN;/* skip header crc */ + + /* if (!keep_cx) */ + /* { */ + dimension = fwData->sec0_size + fwData->sec1_size + + fwData->sec2_size + fwData->sec3_size; + temp = fw_size; + /*} else + * { + * dimension = fwData->sec0_size + fwData->sec1_size; + * temp = fw_size - fwData->sec2_size - fwData->sec3_size; + * fwData->sec2_size = 0; + * fwData->sec3_size = 0; + * }*/ + + if (dimension + FW_HEADER_SIZE + FW_BYTES_ALIGN != temp) { + pr_err("parseBinFile: Read only %d instead of %d... ERROR %08X\n", + fw_size, dimension + FW_HEADER_SIZE + + FW_BYTES_ALIGN, ERROR_FILE_PARSE); + res = ERROR_FILE_PARSE; + goto END; + } + + fwData->data = (u8 *)kmalloc(dimension * sizeof(u8), + GFP_KERNEL); + if (fwData->data == NULL) { + pr_err("parseBinFile: ERROR %08X\n", ERROR_ALLOC); + res = ERROR_ALLOC; + goto END; + } + + index += FW_BYTES_ALIGN; + memcpy(fwData->data, &fw_data[index], dimension); + if (fwData->sec2_size != 0) + u8ToU16(&fwData->data[fwData->sec0_size + + fwData->sec1_size + + FW_CX_VERSION], &fwData->cx_ver); + + else { + pr_err("parseBinFile: Initialize cx_ver to default value!\n"); + fwData->cx_ver = systemInfo.u16_cxVer; + } + + pr_info("parseBinFile: CX Version = %04X\n", fwData->cx_ver); + + fwData->data_size = dimension; + + pr_info("READ FW DONE %d bytes!\n", fwData->data_size); + res = OK; + goto END; + } + +END: + kfree(fw_data); + return res; +} + +/** + * Unlock the flash to be programmed + * @return OK if success or an error code which specify the type of error + */ +int flash_unlock(void) +{ + u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00, + FLASH_UNLOCK_CODE0, FLASH_UNLOCK_CODE1 }; + + pr_info("Command unlock ...\n"); + if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) { + pr_err("flash_unlock: ERROR %08X\n", ERROR_BUS_W); + return ERROR_BUS_W; + } + + pr_info("Unlock flash DONE!\n"); + + return OK; +} + +/** + * Unlock the flash to be erased + * @return OK if success or an error code which specify the type of error + */ +int flash_erase_unlock(void) +{ + u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, + 0x00, + FLASH_ERASE_UNLOCK_CODE0, FLASH_ERASE_UNLOCK_CODE1 }; + + pr_info("Try to erase unlock flash...\n"); + + pr_info("Command erase unlock ...\n"); + if (fts_write(cmd, ARRAY_SIZE(cmd)) < 0) { + pr_err("flash_erase_unlock: ERROR %08X\n", ERROR_BUS_W); + return ERROR_BUS_W; + } + + pr_info("Erase Unlock flash DONE!\n"); + + return OK; +} + +/** + * Erase the full flash + * @return OK if success or an error code which specify the type of error + */ +int flash_full_erase(void) +{ + int status; + + u8 cmd1[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00, + FLASH_ERASE_CODE0 + 1, 0x00 }; + u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00, + FLASH_ERASE_CODE0, FLASH_ERASE_CODE1 }; + + if (fts_write(cmd1, ARRAY_SIZE(cmd1)) < OK) { + pr_err("flash_erase_page_by_page: ERROR %08X\n", ERROR_BUS_W); + return ERROR_BUS_W; + } + + pr_info("Command full erase sent ...\n"); + if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) { + pr_err("flash_full_erase: ERROR %08X\n", ERROR_BUS_W); + return ERROR_BUS_W; + } + + status = wait_for_flash_ready(FLASH_ERASE_CODE0); + + if (status != OK) { + pr_err("flash_full_erase: ERROR %08X\n", ERROR_FLASH_NOT_READY); + return status | ERROR_FLASH_NOT_READY; + /* Flash not ready within the chosen time, better exit! */ + } + + pr_info("Full Erase flash DONE!\n"); + + return OK; +} + +/** + * Erase the flash page by page, giving the possibility to skip the CX area and + * maintain therefore its value + * @param keep_cx if SKIP_PANEL_INIT the Panel Init pages will be skipped, + * if > SKIP_PANEL_CX_INIT Cx and Panel Init pages otherwise all the pages will + * be deleted + * @return OK if success or an error code which specify the type of error + */ +int flash_erase_page_by_page(ErasePage keep_cx) +{ + u8 status, i = 0; + u8 cmd1[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00, + FLASH_ERASE_CODE0 + 1, 0x00 }; + u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00, FLASH_ERASE_CODE0, + 0xA0 }; + u8 cmd2[9] = { FTS_CMD_HW_REG_W, 0x20, 0x00, + 0x01, 0x28, + 0xFF, + 0xFF, 0xFF, 0xFF }; + u8 mask[4] = { 0 }; + char buff[(2 + 1) * 4 + 1]; + int buff_len = sizeof(buff); + int index = 0; + + for (i = FLASH_CX_PAGE_START; i <= FLASH_CX_PAGE_END && keep_cx >= + SKIP_PANEL_CX_INIT; i++) { + pr_info("Skipping erase CX page %d!\n", i); + fromIDtoMask(i, mask, 4); + } + + + for (i = FLASH_PANEL_PAGE_START; i <= FLASH_PANEL_PAGE_END && keep_cx >= + SKIP_PANEL_INIT; i++) { + pr_info("Skipping erase Panel Init page %d!\n", i); + fromIDtoMask(i, mask, 4); + } + + for (i = 0; i < 4; i++) { + cmd2[5 + i] = cmd2[5 + i] & (~mask[i]); + index += scnprintf(buff + index, buff_len - index, + "%02X ", cmd2[5 + i]); + } + pr_info("Setting the page mask = %s\n", buff); + + pr_info("Writing page mask...\n"); + if (fts_write(cmd2, ARRAY_SIZE(cmd2)) < OK) { + pr_err("flash_erase_page_by_page: Page mask ERROR %08X\n", + ERROR_BUS_W); + return ERROR_BUS_W; + } + + if (fts_write(cmd1, ARRAY_SIZE(cmd1)) < OK) { + pr_err("flash_erase_page_by_page: Disable info ERROR %08X\n", + ERROR_BUS_W); + return ERROR_BUS_W; + } + + pr_info("Command erase pages sent ...\n"); + if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) { + pr_err("flash_erase_page_by_page: Erase ERROR %08X\n", + ERROR_BUS_W); + return ERROR_BUS_W; + } + + status = wait_for_flash_ready(FLASH_ERASE_CODE0); + + if (status != OK) { + pr_err("flash_erase_page_by_page: ERROR %08X\n", + ERROR_FLASH_NOT_READY); + return status | ERROR_FLASH_NOT_READY; + /* Flash not ready within the chosen time, better exit! */ + } + + pr_info("Erase flash page by page DONE!\n"); + + return OK; +} + +/** + * Start the DMA procedure which actually transfer and burn the data loaded + * from memory into the Flash + * @return OK if success or an error code which specify the type of error + */ +int start_flash_dma(void) +{ + int status; + u8 cmd[6] = { FLASH_CMD_WRITE_REGISTER, 0x20, 0x00, 0x00, + FLASH_DMA_CODE0, FLASH_DMA_CODE1 }; + + /* write the command to erase the flash */ + + pr_info("Command flash DMA ...\n"); + if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) { + pr_err("start_flash_dma: ERROR %08X\n", ERROR_BUS_W); + return ERROR_BUS_W; + } + + status = wait_for_flash_ready(FLASH_DMA_CODE0); + + if (status != OK) { + pr_err("start_flash_dma: ERROR %08X\n", ERROR_FLASH_NOT_READY); + return status | ERROR_FLASH_NOT_READY; + /* Flash not ready within the chosen time, better exit! */ + } + + pr_info("flash DMA DONE!\n"); + + return OK; +} + +/** + * Copy the FW data that should be burnt in the Flash into the memory and then + * the DMA will take care about burning it into the Flash + * @param address address in memory where to copy the data, possible values + * are FLASH_ADDR_CODE, FLASH_ADDR_CONFIG, FLASH_ADDR_CX + * @param data pointer to an array of byte which contain the data that should + * be copied into the memory + * @param size size of data + * @return OK if success or an error code which specify the type of error + */ +int fillFlash(u32 address, u8 *data, int size) +{ + int remaining = size, index = 0; + int toWrite = 0; + int byteBlock = 0; + int wheel = 0; + u32 addr = 0; + int res; + int delta; + u8 *buff = NULL; + + buff = kmalloc(max(DMA_CHUNK + 5, 12), GFP_KERNEL); + if (buff == NULL) { + pr_err("fillFlash: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + while (remaining > 0) { + byteBlock = 0; + addr = 0x00100000; + + while (byteBlock < FLASH_CHUNK && remaining > 0) { + index = 0; + if (remaining >= DMA_CHUNK) { + if ((byteBlock + DMA_CHUNK) <= FLASH_CHUNK) { + /* pr_err("fillFlash: 1\n"); */ + toWrite = DMA_CHUNK; + remaining -= DMA_CHUNK; + byteBlock += DMA_CHUNK; + } else { + /* pr_err("fillFlash: 2\n); */ + delta = FLASH_CHUNK - byteBlock; + toWrite = delta; + remaining -= delta; + byteBlock += delta; + } + } else { + if ((byteBlock + remaining) <= FLASH_CHUNK) { + /* pr_err("fillFlash: 3\n"); */ + toWrite = remaining; + byteBlock += remaining; + remaining = 0; + } else { + /* pr_err("fillFlash: 4\n"); */ + delta = FLASH_CHUNK - byteBlock; + toWrite = delta; + remaining -= delta; + byteBlock += delta; + } + } + + buff[index++] = FTS_CMD_HW_REG_W; + buff[index++] = (u8)((addr & 0xFF000000) >> 24); + buff[index++] = (u8)((addr & 0x00FF0000) >> 16); + buff[index++] = (u8)((addr & 0x0000FF00) >> 8); + buff[index++] = (u8)(addr & 0x000000FF); + + memcpy(&buff[index], data, toWrite); + /* pr_err("Command = %02X , address = %02X %02X + * , bytes = %d, data = %02X %02X, %02X %02X\n", + * buff[0], buff[1], buff[2], toWrite, buff[3], + * buff[4], buff[3 + toWrite-2], + * buff[3 + toWrite-1]); */ + if (fts_write_heap(buff, index + toWrite) < OK) { + pr_err("fillFlash: ERROR %08X\n", ERROR_BUS_W); + kfree(buff); + return ERROR_BUS_W; + } + + /* mdelay(5); */ + addr += toWrite; + data += toWrite; + } + + + /* configuring the DMA */ + byteBlock = byteBlock / 4 - 1; + index = 0; + + buff[index++] = FLASH_CMD_WRITE_REGISTER; + buff[index++] = 0x20; + buff[index++] = 0x00; + buff[index++] = 0x00; + buff[index++] = FLASH_DMA_CONFIG; + buff[index++] = 0x00; + buff[index++] = 0x00; + + addr = address + ((wheel * FLASH_CHUNK) / 4); + buff[index++] = (u8)((addr & 0x000000FF)); + buff[index++] = (u8)((addr & 0x0000FF00) >> 8); + buff[index++] = (u8)(byteBlock & 0x000000FF); + buff[index++] = (u8)((byteBlock & 0x0000FF00) >> 8); + buff[index++] = 0x00; + + pr_info("DMA Command = %02X , address = %02X %02X, words = %02X %02X\n", + buff[0], buff[8], buff[7], buff[10], buff[9]); + + if (fts_write_heap(buff, index) < OK) { + pr_err("Error during filling Flash! ERROR %08X\n", + ERROR_BUS_W); + kfree(buff); + return ERROR_BUS_W; + } + + res = start_flash_dma(); + if (res < OK) { + pr_err("Error during flashing DMA! ERROR %08X\n", res); + kfree(buff); + return res; + } + wheel++; + } + kfree(buff); + return OK; +} + + +/* + * Execute the procedure to burn a FW on FTM5/FTI IC + * + * @param fw - structure which contain the FW to be burnt + * @param force_burn - if >0, the flashing procedure will be forced and + * executed + * regardless the additional info, otherwise the FW in the file will be + * burned only if it is different from the one running in the IC + * @param keep_cx - if 1, the function preserves the CX/Panel Init area. + * Otherwise, it will be cleared. + * + * @return OK if success or an error code which specifies the type of error + * encountered + */ +int flash_burn(Firmware fw, int force_burn, int keep_cx) +{ + int res; + + if (!force_burn) { + /* Compare firmware, config, and CX versions */ + if (fw.fw_ver != (uint32_t)systemInfo.u16_fwVer || + fw.config_ver != (uint32_t)systemInfo.u16_cfgVer || + fw.cx_ver != (uint32_t)systemInfo.u16_cxVer) + goto start; + + for (res = EXTERNAL_RELEASE_INFO_SIZE - 1; res >= 0; res--) { + if (fw.externalRelease[res] != + systemInfo.u8_releaseInfo[res]) + goto start; + } + + pr_info("flash_burn: Firmware in the chip matches the firmware to flash! NO UPDATE ERROR %08X\n", + ERROR_FW_NO_UPDATE); + return ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED; + } else if (force_burn == CRC_CX && fw.sec2_size == 0) { + /* burn procedure to update the CX memory, if not present just + * skip it! + */ + for (res = EXTERNAL_RELEASE_INFO_SIZE - 1; res >= 0; res--) { + if (fw.externalRelease[res] != + systemInfo.u8_releaseInfo[res]) { + /* Avoid loading the CX because it is missing + * in the bin file, it just need to update + * to last fw+cfg because a new release */ + force_burn = 0; + goto start; + } + } + pr_info("flash_burn: CRC in CX but fw does not contain CX data! NO UPDATE ERROR %08X\n", + ERROR_FW_NO_UPDATE); + return ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED; + } + + /* Programming procedure start */ +start: + pr_info("Programming Procedure for flashing started:\n"); + + pr_info(" 1) SYSTEM RESET:\n"); + res = fts_system_reset(); + if (res < 0) { + pr_err(" system reset FAILED!\n"); + /* If there is no firmware, there is no controller ready event + * and there will be a timeout, we can keep going. But if + * there is an I2C error, we must exit. + */ + if (res != (ERROR_SYSTEM_RESET_FAIL | ERROR_TIMEOUT)) + return res | ERROR_FLASH_BURN_FAILED; + } else + pr_info(" system reset COMPLETED!\n"); + + msleep(100); /* required by HW for safe flash procedure */ + + pr_info(" 2) HOLD M3 :\n"); + + res = hold_m3(); + if (res < OK) { + pr_err(" hold_m3 FAILED!\n"); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" hold_m3 COMPLETED!\n"); + + pr_info(" 3) FLASH UNLOCK:\n"); + res = flash_unlock(); + if (res < OK) { + pr_err(" flash unlock FAILED! ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" flash unlock COMPLETED!\n"); + + pr_info(" 4) FLASH ERASE UNLOCK:\n"); + res = flash_erase_unlock(); + if (res < 0) { + pr_err(" flash unlock FAILED! ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" flash unlock COMPLETED!\n"); + + pr_info(" 5) FLASH ERASE:\n"); + if (keep_cx > 0) { + if (fw.sec2_size != 0) + res = flash_erase_page_by_page(SKIP_PANEL_INIT); + else + res = flash_erase_page_by_page(SKIP_PANEL_CX_INIT); + } else { + res = flash_erase_page_by_page(SKIP_PANEL_INIT); + if (fw.sec2_size == 0) + pr_err("WARNING!!! Erasing CX memory but no CX in fw file! touch will not work right after fw update!\n"); + } + + if (res < OK) { + pr_err(" flash erase FAILED! ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" flash erase COMPLETED!\n"); + + pr_info(" 6) LOAD PROGRAM:\n"); + res = fillFlash(FLASH_ADDR_CODE, &fw.data[0], fw.sec0_size); + if (res < OK) { + pr_err(" load program ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" load program DONE!\n"); + + pr_info(" 7) LOAD CONFIG:\n"); + res = fillFlash(FLASH_ADDR_CONFIG, &(fw.data[fw.sec0_size]), + fw.sec1_size); + if (res < OK) { + pr_err(" load config ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" load config DONE!\n"); + + if (fw.sec2_size != 0 && (force_burn == CRC_CX || keep_cx <= 0)) { + pr_info(" 7.1) LOAD CX:\n"); + res = fillFlash(FLASH_ADDR_CX, + &(fw.data[fw.sec0_size + fw.sec1_size]), + fw.sec2_size); + if (res < OK) { + pr_err(" load cx ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" load cx DONE!\n"); + } + + pr_info(" Flash burn COMPLETED!\n"); + + pr_info(" 8) SYSTEM RESET:\n"); + res = fts_system_reset(); + if (res < 0) { + pr_err(" system reset FAILED! ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + pr_info(" system reset COMPLETED!\n"); + + pr_info(" 9) FINAL CHECK:\n"); + res = readSysInfo(0); + if (res < 0) { + pr_err("flash_burn: Unable to retrieve Chip INFO! ERROR %08X\n", + ERROR_FLASH_BURN_FAILED); + return res | ERROR_FLASH_BURN_FAILED; + } + + for (res = 0; res < EXTERNAL_RELEASE_INFO_SIZE; res++) { + if (fw.externalRelease[res] != systemInfo.u8_releaseInfo[res]) { + /* External release is printed during readSysInfo */ + pr_info(" Firmware in the chip different from the one that was burn!\n"); + return ERROR_FLASH_BURN_FAILED; + } + } + + pr_info(" Final check OK!\n"); + + return OK; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFlash.h b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.h new file mode 100644 index 000000000000..708c8ba2ff7a --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.h @@ -0,0 +1,115 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS API for Flashing the IC * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsFlash.h + * \brief Contains all the definitions and structs to handle the FW update + *process + */ + +#ifndef FTS_FLASH_H +#define FTS_FLASH_H + +#include "ftsSoftware.h" + +/* Flash possible status */ +#define FLASH_READY 0 /* /< value to indicate that the flash + * is ready */ +#define FLASH_BUSY 1 /* /< value to indicate that the flash + * is busy */ +#define FLASH_UNKNOWN -1 /* /< value to indicate an unknown + * status of the flash */ + +#define FLASH_STATUS_BYTES 1 /* /< number of bytes to check for read + * the flash status */ + + + +/* Flash timing parameters */ +#define FLASH_RETRY_COUNT 200 /* /< number of attempts to read the + * flash status */ +#define FLASH_WAIT_BEFORE_RETRY 50 /* /< time to wait in ms between status + * readings */ + + +#ifdef FW_H_FILE +#define PATH_FILE_FW "NULL" +#else +#define PATH_FILE_FW "ftm5_fw.ftb" /* new FW bin file name */ +#endif + +#define FLASH_CHUNK (64 * 1024) /* /< Max number of bytes that + * the DMA can burn on the flash + * in one shot in FTI */ +#define DMA_CHUNK 32 /* /< Max number of bytes that can be + * written in I2C to the DMA */ + +/** + * Define which kind of erase page by page should be performed + */ +typedef enum { + ERASE_ALL = 0, /* /< erase all the pages */ + SKIP_PANEL_INIT = 1, /* /< skip erase Panel Init Pages */ + SKIP_PANEL_CX_INIT = 2 /* /< skip erase Panel Init and CX Pages */ +} ErasePage; + +/** @addtogroup fw_file + * @{ + */ + +/** + * Struct which contains information and data of the FW that should be burnt + *into the IC + */ +typedef struct { + u8 *data; /* /< pointer to an array of bytes which represent the + * FW data */ + u16 fw_ver; /* /< FW version of the FW file */ + u16 config_ver; /* Config version of the FW file */ + u16 cx_ver; /* /< Cx version of the FW file */ + u8 externalRelease[EXTERNAL_RELEASE_INFO_SIZE]; /* /< External Release + * Info of the FW file + * */ + int data_size; /* /< dimension of data (the actual data to be burnt) */ + u32 sec0_size; /* /< dimension of section 0 (FW) in .ftb file */ + u32 sec1_size; /* /< dimension of section 1 (Config) in .ftb file */ + u32 sec2_size; /* /< dimension of section 2 (Cx) in .ftb file */ + u32 sec3_size; /* /< dimension of section 3 (TBD) in .ftb file */ +} Firmware; + +/** @}*/ + +/** @addtogroup flash_command + * @{ + */ + +int wait_for_flash_ready(u8 type); +int hold_m3(void); +int flash_erase_unlock(void); +int flash_full_erase(void); +int flash_erase_page_by_page(ErasePage keep_cx); +int start_flash_dma(void); +int fillFlash(u32 address, u8 *data, int size); + +int flash_unlock(void); +int getFWdata(const char *pathToFile, u8 **data, int *size); +int parseBinFile(u8 *fw_data, int fw_size, Firmware *fw, int keep_cx); +int readFwFile(const char *path, Firmware *fw, int keep_cx); +int flash_burn(Firmware fw, int force_burn, int keep_cx); +int flashProcedure(const char *path, int force, int keep_cx); + +#endif + +/** @}*/ diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFrame.c b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.c new file mode 100644 index 000000000000..a18a273070c6 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.c @@ -0,0 +1,620 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS functions for getting frames * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsFrame.c + * \brief Contains all the functions to work with frames + */ + +#include "ftsCompensation.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsFrame.h" +#include "ftsHardware.h" +#include "ftsIO.h" +#include "ftsSoftware.h" +#include "ftsTool.h" +#include "ftsTime.h" + + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/serio.h> +#include <linux/time.h> +#include <linux/delay.h> +#include <linux/ctype.h> + + + + + +extern SysInfo systemInfo; /* /< forward declaration of the global variable + * of containing System Info Data */ + + +/** + * Read the channels lengths from the config memory + * @return OK if success or an error code which specify the type of error + */ +int getChannelsLength(void) +{ + int ret; + u8 data[2]; + + if (data == NULL) { + pr_err("getChannelsLength: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + ret = readConfig(ADDR_CONFIG_SENSE_LEN, data, 2); + if (ret < OK) { + pr_err("getChannelsLength: ERROR %08X\n", ret); + + return ret; + } + + systemInfo.u8_scrRxLen = (int)data[0]; + systemInfo.u8_scrTxLen = (int)data[1]; + + pr_info("Force_len = %d Sense_Len = %d\n", + systemInfo.u8_scrTxLen, systemInfo.u8_scrRxLen); + + return OK; +} + + + +/** + * Read and pack the frame data related to the nodes + * @param address address in memory when the frame data node start + * @param size amount of data to read + * @param frame pointer to an array of bytes which will contain the frame node + * data + * @return OK if success or an error code which specify the type of error + */ +int getFrameData(u16 address, int size, short *frame) +{ + int i, j, ret; + u8 *data = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL); + + if (data == NULL) { + pr_err("getFrameData: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data, + size, DUMMY_FRAMEBUFFER); + if (ret < OK) { + pr_err("getFrameData: ERROR %08X\n", ERROR_BUS_R); + kfree(data); + return ERROR_BUS_R; + } + j = 0; + for (i = 0; i < size; i += 2) { + frame[j] = (short)((data[i + 1] << 8) + data[i]); + j++; + } + kfree(data); + return OK; +} + + +/** + * Return the number of Sense Channels (Rx) + * @return number of Rx channels + */ +int getSenseLen(void) +{ + if (systemInfo.u8_scrRxLen == 0) + getChannelsLength(); + return systemInfo.u8_scrRxLen; +} + +/** + * Return the number of Force Channels (Tx) + * @return number of Tx channels + */ +int getForceLen(void) +{ + if (systemInfo.u8_scrTxLen == 0) + getChannelsLength(); + return systemInfo.u8_scrTxLen; +} + + +/******************** New API **************************/ + +/** + * Read a MS Frame from frame buffer memory + * @param type type of MS frame to read + * @param frame pointer to MutualSenseFrame variable which will contain the + * data + * @return > 0 if success specifying the number of node into the frame or + * an error code which specify the type of error + */ +int getMSFrame3(MSFrameType type, MutualSenseFrame *frame) +{ + u16 offset; + int ret, force_len, sense_len; + + force_len = getForceLen(); + sense_len = getSenseLen(); + + frame->node_data = NULL; + + pr_info("%s: Starting to get frame %02X\n", __func__, + type); + switch (type) { + case MS_RAW: + offset = systemInfo.u16_msTchRawAddr; + goto LOAD_NORM; + case MS_FILTER: + offset = systemInfo.u16_msTchFilterAddr; + + goto LOAD_NORM; + case MS_STRENGTH: + offset = systemInfo.u16_msTchStrenAddr; + goto LOAD_NORM; + case MS_BASELINE: + offset = systemInfo.u16_msTchBaselineAddr; +LOAD_NORM: + if (force_len == 0 || sense_len == 0) { + pr_err("%s: number of channels not initialized ERROR %08X\n", + __func__, ERROR_CH_LEN); + return ERROR_CH_LEN | ERROR_GET_FRAME; + } + + break; + + case MS_KEY_RAW: + offset = systemInfo.u16_keyRawAddr; + goto LOAD_KEY; + case MS_KEY_FILTER: + offset = systemInfo.u16_keyFilterAddr; + goto LOAD_KEY; + case MS_KEY_STRENGTH: + offset = systemInfo.u16_keyStrenAddr; + goto LOAD_KEY; + case MS_KEY_BASELINE: + offset = systemInfo.u16_keyBaselineAddr; +LOAD_KEY: + if (systemInfo.u8_keyLen == 0) { + pr_err("%s: number of channels not initialized ERROR %08X\n", + __func__, ERROR_CH_LEN); + return ERROR_CH_LEN | ERROR_GET_FRAME; + } + force_len = 1; + sense_len = systemInfo.u8_keyLen; + break; + + case FRC_RAW: + offset = systemInfo.u16_frcRawAddr; + goto LOAD_FRC; + case FRC_FILTER: + offset = systemInfo.u16_frcFilterAddr; + goto LOAD_FRC; + case FRC_STRENGTH: + offset = systemInfo.u16_frcStrenAddr; + goto LOAD_FRC; + case FRC_BASELINE: + offset = systemInfo.u16_frcBaselineAddr; +LOAD_FRC: + if (force_len == 0) { + pr_err("%s: number of channels not initialized ERROR %08X\n", + __func__, ERROR_CH_LEN); + return ERROR_CH_LEN | ERROR_GET_FRAME; + } + sense_len = 1; + break; + default: + pr_err("%s: Invalid type ERROR %08X\n", __func__, + ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME); + return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME; + } + + frame->node_data_size = ((force_len) * sense_len); + frame->header.force_node = force_len; + frame->header.sense_node = sense_len; + frame->header.type = type; + + pr_info("%s: Force_len = %d Sense_len = %d Offset = %04X\n", + __func__, force_len, sense_len, offset); + + frame->node_data = (short *)kmalloc(frame->node_data_size * + sizeof(short), GFP_KERNEL); + if (frame->node_data == NULL) { + pr_err("%s: ERROR %08X\n", __func__, + ERROR_ALLOC | ERROR_GET_FRAME); + return ERROR_ALLOC | ERROR_GET_FRAME; + } + + ret = getFrameData(offset, frame->node_data_size * BYTES_PER_NODE, + (frame->node_data)); + if (ret < OK) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_GET_FRAME_DATA); + kfree(frame->node_data); + frame->node_data = NULL; + return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; + } + /* if you want to access one node i,j, + * compute the offset like: offset = i*columns + j = > frame[i, j] */ + + pr_info("Frame acquired!\n"); + return frame->node_data_size; + /* return the number of data put inside frame */ +} + +/** + * Read a SS Frame from frame buffer + * @param type type of SS frame to read + * @param frame pointer to SelfSenseFrame variable which will contain the data + * @return > 0 if success specifying the number of node into frame or an + * error code which specify the type of error + */ +int getSSFrame3(SSFrameType type, SelfSenseFrame *frame) +{ + u16 offset_force, offset_sense; + int ret; + + frame->force_data = NULL; + frame->sense_data = NULL; + + frame->header.force_node = getForceLen(); /* use getForce/SenseLen + * because introduce + * a recover mechanism + * in case of len =0 */ + frame->header.sense_node = getSenseLen(); + + if (frame->header.force_node == 0 || frame->header.sense_node == 0) { + pr_err("%s: number of channels not initialized ERROR %08X\n", + __func__, ERROR_CH_LEN); + return ERROR_CH_LEN | ERROR_GET_FRAME; + } + + + pr_info("%s: Starting to get frame %02X\n", __func__, type); + switch (type) { + case SS_RAW: + offset_force = systemInfo.u16_ssTchTxRawAddr; + offset_sense = systemInfo.u16_ssTchRxRawAddr; + break; + case SS_FILTER: + offset_force = systemInfo.u16_ssTchTxFilterAddr; + offset_sense = systemInfo.u16_ssTchRxFilterAddr; + break; + case SS_STRENGTH: + offset_force = systemInfo.u16_ssTchTxStrenAddr; + offset_sense = systemInfo.u16_ssTchRxStrenAddr; + break; + case SS_BASELINE: + offset_force = systemInfo.u16_ssTchTxBaselineAddr; + offset_sense = systemInfo.u16_ssTchRxBaselineAddr; + break; + + case SS_HVR_RAW: + offset_force = systemInfo.u16_ssHvrTxRawAddr; + offset_sense = systemInfo.u16_ssHvrRxRawAddr; + break; + case SS_HVR_FILTER: + offset_force = systemInfo.u16_ssHvrTxFilterAddr; + offset_sense = systemInfo.u16_ssHvrRxFilterAddr; + break; + case SS_HVR_STRENGTH: + offset_force = systemInfo.u16_ssHvrTxStrenAddr; + offset_sense = systemInfo.u16_ssHvrRxStrenAddr; + break; + case SS_HVR_BASELINE: + offset_force = systemInfo.u16_ssHvrTxBaselineAddr; + offset_sense = systemInfo.u16_ssHvrRxBaselineAddr; + break; + + case SS_PRX_RAW: + offset_force = systemInfo.u16_ssPrxTxRawAddr; + offset_sense = systemInfo.u16_ssPrxRxRawAddr; + break; + case SS_PRX_FILTER: + offset_force = systemInfo.u16_ssPrxTxFilterAddr; + offset_sense = systemInfo.u16_ssPrxRxFilterAddr; + break; + case SS_PRX_STRENGTH: + offset_force = systemInfo.u16_ssPrxTxStrenAddr; + offset_sense = systemInfo.u16_ssPrxRxStrenAddr; + break; + case SS_PRX_BASELINE: + offset_force = systemInfo.u16_ssPrxTxBaselineAddr; + offset_sense = systemInfo.u16_ssPrxRxBaselineAddr; + break; + + default: + pr_err("%s: Invalid type ERROR %08X\n", __func__, + ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME); + return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME; + } + + frame->header.type = type; + + pr_info("%s: Force_len = %d Sense_len = %d Offset_force = %04X Offset_sense = %04X\n", + __func__, frame->header.force_node, + frame->header.sense_node, + offset_force, offset_sense); + + frame->force_data = (short *)kmalloc(frame->header.force_node * + sizeof(short), GFP_KERNEL); + if (frame->force_data == NULL) { + pr_err("%s: can not allocate force_data ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + return ERROR_ALLOC | ERROR_GET_FRAME; + } + + frame->sense_data = (short *)kmalloc(frame->header.sense_node * + sizeof(short), GFP_KERNEL); + if (frame->sense_data == NULL) { + kfree(frame->force_data); + frame->force_data = NULL; + pr_err("%s: can not allocate sense_data ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + return ERROR_ALLOC | ERROR_GET_FRAME; + } + + ret = getFrameData(offset_force, frame->header.force_node * + BYTES_PER_NODE, (frame->force_data)); + if (ret < OK) { + pr_err("%s: error while reading force data ERROR %08X\n", + __func__, ERROR_GET_FRAME_DATA); + kfree(frame->force_data); + frame->force_data = NULL; + kfree(frame->sense_data); + frame->sense_data = NULL; + return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; + } + + ret = getFrameData(offset_sense, frame->header.sense_node * + BYTES_PER_NODE, (frame->sense_data)); + if (ret < OK) { + pr_err("%s: error while reading sense data ERROR %08X\n", + __func__, ERROR_GET_FRAME_DATA); + kfree(frame->force_data); + frame->force_data = NULL; + kfree(frame->sense_data); + frame->sense_data = NULL; + return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; + } + /* if you want to access one node i,j, + * the offset like: offset = i*columns + j = > frame[i, j] */ + + pr_info("Frame acquired!\n"); + return frame->header.force_node + frame->header.sense_node; + /* return the number of data put inside frame */ +} + + +/** + * Read Initialization Data Header and check that the type loaded match with + * the one previously requested + * @param type type of Initialization data requested @link load_opt Load Host + * Data Option @endlink + * @param msHeader pointer to DataHeader variable which will contain the header + * info for the MS frame + * @param ssHeader pointer to DataHeader variable which will contain the header + * info for the SS frame + * @param address pointer to a variable which will contain the updated address + * to the next data + * @return OK if success or an error code which specify the type of error + */ +int readSyncDataHeader(u8 type, DataHeader *msHeader, DataHeader *ssHeader, + u64 *address) +{ + u64 offset = ADDR_FRAMEBUFFER; + u8 data[SYNCFRAME_DATA_HEADER]; + int ret; + + ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data, + SYNCFRAME_DATA_HEADER, DUMMY_FRAMEBUFFER); + if (ret < OK) { /* i2c function have already a retry mechanism */ + pr_err("%s: error while reading data header ERROR %08X\n", + __func__, ret); + return ret; + } + + pr_info("Read Data Header done!\n"); + + if (data[0] != HEADER_SIGNATURE) { + pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n", + __func__, data[0], HEADER_SIGNATURE, + ERROR_WRONG_DATA_SIGN); + return ERROR_WRONG_DATA_SIGN; + } + + + if (data[1] != type) { + pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n", + __func__, data[1], type, ERROR_DIFF_DATA_TYPE); + return ERROR_DIFF_DATA_TYPE; + } + + pr_info("Type = %02X of SyncFrame data OK!\n", type); + + msHeader->force_node = data[5]; + msHeader->sense_node = data[6]; + pr_info("MS Frame force_node = %d, sense_node = %d\n", + msHeader->force_node, msHeader->sense_node); + + ssHeader->force_node = data[7]; + ssHeader->sense_node = data[8]; + pr_info("SS Frame force_node = %d, sense_node = %d\n", + ssHeader->force_node, ssHeader->sense_node); + + *address = offset + SYNCFRAME_DATA_HEADER + data[4]; + + return OK; +} + +/** + * Read a Sync Frame from frame buffer which contain MS and SS data collected + * for the same scan + * @param type type of Sync frame to read, possible values: + * LOAD_SYNC_FRAME_RAW, LOAD_SYNC_FRAME_FILTER, LOAD_SYNC_FRAME_BASELINE, + * LOAD_SYNC_FRAME_STRENGTH + * @param msFrame pointer to MutualSenseFrame variable which will contain the + * MS data + * @param ssFrame pointer to SelfSenseFrame variable which will contain the SS + * data + * @return >0 if success specifying the total number of nodes copied into + * msFrame and ssFrame or an error code which specify the type of error + */ +int getSyncFrame(u8 type, MutualSenseFrame *msFrame, SelfSenseFrame *ssFrame) +{ + int res; + u64 address; + + msFrame->node_data = NULL; + ssFrame->force_data = NULL; + ssFrame->sense_data = NULL; + + pr_info("%s: Starting to get Sync Frame %02X...\n", __func__, type); + switch (type) { + case LOAD_SYNC_FRAME_RAW: + msFrame->header.type = MS_RAW; + ssFrame->header.type = SS_RAW; + break; + + case LOAD_SYNC_FRAME_FILTER: + msFrame->header.type = MS_FILTER; + ssFrame->header.type = SS_FILTER; + break; + + case LOAD_SYNC_FRAME_BASELINE: + msFrame->header.type = MS_BASELINE; + ssFrame->header.type = SS_BASELINE; + break; + + case LOAD_SYNC_FRAME_STRENGTH: + msFrame->header.type = MS_STRENGTH; + ssFrame->header.type = SS_STRENGTH; + break; + + default: + return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME; + } + + pr_info("%s: Requesting Sync Frame %02X...\n", __func__, type); + res = requestSyncFrame(type); + if (res < OK) { + pr_err("%s: error while requesting Sync Frame ERROR %08X\n", + __func__, res | ERROR_GET_FRAME_DATA); + return res | ERROR_GET_FRAME_DATA; + } + + res = readSyncDataHeader(type, &(msFrame->header), &(ssFrame->header), + &address); + if (res < OK) { + pr_err("%s: error while reading Sync Frame header... ERROR %08X\n", + __func__, res | ERROR_GET_FRAME_DATA); + return res | ERROR_GET_FRAME_DATA; + } + + msFrame->node_data_size = msFrame->header.force_node * + msFrame->header.sense_node; + + msFrame->node_data = (short *)kmalloc(msFrame->node_data_size * + sizeof(short), GFP_KERNEL); + if (msFrame->node_data == NULL) { + pr_err("%s: impossible allocate memory for MS frame... ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + return ERROR_ALLOC | ERROR_GET_FRAME; + } + + pr_info("%s: Getting MS frame at %llx...\n", __func__, address); + res = getFrameData(address, (msFrame->node_data_size) * BYTES_PER_NODE, + (msFrame->node_data)); + if (res < OK) { + pr_err("%s: error while getting MS data...ERROR %08X\n", + __func__, res); + res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; + goto ERROR; + } + + /* move the offset */ + address += (msFrame->node_data_size) * BYTES_PER_NODE; + + ssFrame->force_data = (short *)kmalloc(ssFrame->header.force_node * + sizeof(short), GFP_KERNEL); + if (ssFrame->force_data == NULL) { + pr_err("%s: impossible allocate memory for SS force frame...ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + res = ERROR_ALLOC | ERROR_GET_FRAME; + goto ERROR; + } + + pr_info("%s: Getting SS force frame at %llx...\n", __func__, address); + res = getFrameData(address, (ssFrame->header.force_node) * + BYTES_PER_NODE, (ssFrame->force_data)); + if (res < OK) { + pr_err("%s: error while getting SS force data...ERROR %08X\n", + __func__, res); + res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; + goto ERROR; + } + + /* move the offset */ + address += (ssFrame->header.force_node) * BYTES_PER_NODE; + + ssFrame->sense_data = (short *)kmalloc(ssFrame->header.sense_node * + sizeof(short), GFP_KERNEL); + if (ssFrame->sense_data == NULL) { + pr_err("%s: impossible allocate memory for SS sense frame...ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + res = ERROR_ALLOC | ERROR_GET_FRAME; + goto ERROR; + } + + pr_info("%s: Getting SS sense frame at %llx...\n", __func__, address); + res = getFrameData(address, (ssFrame->header.sense_node) * + BYTES_PER_NODE, (ssFrame->sense_data)); + if (res < OK) { + pr_err("%s: error while getting SS sense data...ERROR %08X\n", + __func__, res); + res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME; + goto ERROR; + } + +ERROR: + if (res < OK) { + if (msFrame->node_data != NULL) { + kfree(msFrame->node_data); + msFrame->node_data = NULL; + } + + if (ssFrame->force_data != NULL) { + kfree(ssFrame->force_data); + ssFrame->force_data = NULL; + } + + if (ssFrame->sense_data != NULL) { + kfree(ssFrame->sense_data); + ssFrame->sense_data = NULL; + } + pr_err("Getting Sync Frame FAILED! ERROR %08X!\n", res); + } else { + pr_info("Getting Sync Frame FINISHED!\n"); + res = msFrame->node_data_size + ssFrame->header.force_node + + ssFrame->header.sense_node; + } + return res; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFrame.h b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.h new file mode 100644 index 000000000000..bdd51256dd8f --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.h @@ -0,0 +1,113 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS functions for getting frames * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsFrame.h + * \brief Contains all the definitions and structs to work with frames + */ + + +#ifndef FTS_FRAME_H +#define FTS_FRAME_H + +#include "ftsSoftware.h" +#include "ftsCore.h" + + + +/* Number of data bytes for each node */ +#define BYTES_PER_NODE 2 /* /< number of data bytes for each node + * */ + + +#define RETRY_FRAME_DATA_READ 2 /* /< max number of attempts to read a + * frame */ +#define SYNCFRAME_DATA_HEADER (DATA_HEADER + 12) /* /< number of bytes of + * Sync Frame Header */ + +/** + * Possible types of MS frames + */ +typedef enum { + MS_RAW = 0, /* /< Mutual Sense Raw Frame */ + MS_FILTER = 1, /* /< Mutual Sense Filtered Frame */ + MS_STRENGTH = 2, /* /< Mutual Sense Strength Frame (Baseline-Raw) + * */ + MS_BASELINE = 3, /* /< Mutual Sense Baseline Frame */ + MS_KEY_RAW = 4, /* /< Mutual Sense Key Raw Frame */ + MS_KEY_FILTER = 5, /* /< Mutual Sense Key Filter Frame */ + MS_KEY_STRENGTH = 6, /* /< Mutual Sense Key Strength Frame + * (Baseline-Raw) */ + MS_KEY_BASELINE = 7, /* /< Mutual Sense Key Baseline Frame */ + FRC_RAW = 8, /* /< Force Raw Frame */ + FRC_FILTER = 9, /* /< Force Filtered Frame */ + FRC_STRENGTH = 10, /* /< Force Strength Frame (Baseline-Raw) */ + FRC_BASELINE = 11 /* /< Force Baseline Frame */ +} MSFrameType; + + +/** + * Possible types of SS frames + */ +typedef enum { + SS_RAW = 0, /* /< Self Sense Raw Frame */ + SS_FILTER = 1, /* /< Self Sense Filtered Frame */ + SS_STRENGTH = 2, /* /< Self Sense Strength Frame (Baseline-Raw) + * */ + SS_BASELINE = 3, /* /< Self Sense Baseline Frame */ + SS_HVR_RAW = 4, /* /< Self Sense Hover Raw Frame */ + SS_HVR_FILTER = 5, /* /< Self Sense Hover Filter Frame */ + SS_HVR_STRENGTH = 6, /* /< Self Sense Hover Strength Frame + * (Baseline-Raw) */ + SS_HVR_BASELINE = 7, /* /< Self Sense Hover Baseline Frame */ + SS_PRX_RAW = 8, /* /< Self Sense Proximity Raw Frame */ + SS_PRX_FILTER = 9, /* /< Self Sense Proximity Filtered Frame */ + SS_PRX_STRENGTH = 10, /* /< Self Sense Proximity Strength Frame + * (Baseline-Raw) */ + SS_PRX_BASELINE = 11 /* /< Self Sense Proximity Baseline Frame */ +} SSFrameType; + + +/** + * Struct which contains the data of a MS Frame + */ +typedef struct { + DataHeader header; /* /< Header which contain basic info of the + * frame */ + short *node_data; /* /< Data of the frame */ + int node_data_size; /* /< Dimension of the data of the frame */ +} MutualSenseFrame; + +/** + * Struct which contains the data of a SS Frame + */ +typedef struct { + DataHeader header; /* /< Header which contain basic info of the + * frame */ + short *force_data; /* /< Force Channels Data */ + short *sense_data; /* /< Sense Channels Data */ +} SelfSenseFrame; + + +int getChannelsLength(void); +int getFrameData(u16 address, int size, short *frame); +int getSenseLen(void); +int getForceLen(void); +int getMSFrame3(MSFrameType type, MutualSenseFrame *frame); +int getSSFrame3(SSFrameType type, SelfSenseFrame *frame); +int readSyncDataHeader(u8 type, DataHeader *msHeader, DataHeader *ssHeader, + u64 *address); +int getSyncFrame(u8 type, MutualSenseFrame *msFrame, SelfSenseFrame *ssFrame); +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c new file mode 100644 index 000000000000..904c2ef8c90c --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c @@ -0,0 +1,376 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Gesture Utilities ** + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsGesture.c + * \brief Contains all the functions and variable to handle the Gesture + * Detection features + */ + +#include "ftsSoftware.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsGesture.h" +#include "ftsIO.h" +#include "ftsTime.h" +#include "ftsTool.h" + +/* /< store the gesture bitmask which the host want to enable. + * If bit set 1 the corresponding gesture will be detected in Gesture Mode */ +static u8 gesture_mask[GESTURE_MASK_SIZE] = { 0 }; +/* /< store the x coordinates of the points draw by the user + * when a gesture is detected */ +u16 gesture_coordinates_x[GESTURE_MAX_COORDS_PAIRS_REPORT] = { 0 }; +/* /< store the y coordinates of the points draw by the user + * when a gesture is detected */ +u16 gesture_coordinates_y[GESTURE_MAX_COORDS_PAIRS_REPORT] = { 0 }; +/* /< number of coordinates pairs (points) reported with the detected gesture */ +int gesture_coords_reported = ERROR_OP_NOT_ALLOW; +static u8 refreshGestureMask; /* /< flag which indicate if there is + * the need to set the gesture mask in the FW */ +struct mutex gestureMask_mutex; /* /< mutex used to control access on gesture + * shared variables */ + +/** + * Update the gesture mask stored in the driver and have to be used in gesture + * mode + * @param mask pointer to a byte array which store the gesture mask update + * that want to be performed. + * @param size dimension in byte of mask. This size can be <= + * GESTURE_MASK_SIZE. + * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos + * and starting from the less significant byte. + * @param en 0 = enable the gestures set in mask, 1 = disable the gestures set + * in mask + * @return OK if success or an error code which specify the type of error + */ +int updateGestureMask(u8 *mask, int size, int en) +{ + u8 temp; + int i; + + if (mask != NULL) { + if (size <= GESTURE_MASK_SIZE) { + if (en == FEAT_ENABLE) { + mutex_lock(&gestureMask_mutex); + pr_info("updateGestureMask: setting gesture mask to enable...\n"); + if (mask != NULL) + for (i = 0; i < size; i++) + gesture_mask[i] = + gesture_mask[i] | + mask[i]; + /* back up of the gesture enabled */ + refreshGestureMask = 1; + pr_info("updateGestureMask: gesture mask to enable SET!\n"); + mutex_unlock(&gestureMask_mutex); + return OK; + } else if (en == FEAT_DISABLE) { + mutex_lock(&gestureMask_mutex); + pr_info("updateGestureMask: setting gesture mask to disable...\n"); + for (i = 0; i < size; i++) { + temp = gesture_mask[i] ^ mask[i]; + /* enabled XOR disabled */ + gesture_mask[i] = temp & + gesture_mask[i]; + /* temp AND enabled + * disable the gestures that were + * enabled */ + } + pr_info("updateGestureMask: gesture mask to disable SET!\n"); + refreshGestureMask = 1; + mutex_unlock(&gestureMask_mutex); + return OK; + } else { + pr_err("updateGestureMask: Enable parameter Invalid! %d != %d or %d ERROR %08X", + en, + FEAT_DISABLE, FEAT_ENABLE, + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("updateGestureMask: Size not valid! %d > %d ERROR %08X\n", + size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("updateGestureMask: Mask NULL! ERROR %08X\n", + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Enable in the FW the gesture mask to be used in gesture mode + * @param mask pointer to a byte array which store the gesture mask update + * that want to be sent to the FW, if NULL, will be used gesture_mask + * set previously without any changes. + * @param size dimension in byte of mask. This size can be <= + * GESTURE_MASK_SIZE. + * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos and + * starting from the less significant byte. + * @return OK if success or an error code which specify the type of error + */ +int enableGesture(u8 *mask, int size) +{ + int i, res; + + pr_info("Trying to enable gesture...\n"); + + if (size <= GESTURE_MASK_SIZE) { + mutex_lock(&gestureMask_mutex); + if (mask != NULL) + for (i = 0; i < size; i++) + gesture_mask[i] = gesture_mask[i] | mask[i]; + /* back up of the gesture enabled */ + + res = setFeatures(FEAT_SEL_GESTURE, gesture_mask, + GESTURE_MASK_SIZE); + if (res < OK) { + pr_err("enableGesture: ERROR %08X\n", res); + goto END; + } + + pr_info("enableGesture DONE!\n"); + res = OK; + +END: + mutex_unlock(&gestureMask_mutex); + return res; + } else { + pr_err("enableGesture: Size not valid! %d > %d ERROR %08X\n", + size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Disable in the FW the gesture mask to be used in gesture mode + * @param mask pointer to a byte array which store the gesture mask update that + * want to be sent to the FW, if NULL, all the gestures will be disabled. + * @param size dimension in byte of mask. This size can be <= + * GESTURE_MASK_SIZE. + * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos and + * starting from the less significant byte. + * @return OK if success or an error code which specify the type of error + */ +int disableGesture(u8 *mask, int size) +{ + u8 temp; + int i, res; + u8 *pointer; + + + pr_info("Trying to disable gesture...\n"); + + + if (size <= GESTURE_MASK_SIZE) { + mutex_lock(&gestureMask_mutex); + if (mask != NULL) { + for (i = 0; i < size; i++) { + temp = gesture_mask[i] ^ mask[i]; + /* enabled mask XOR disabled mask */ + gesture_mask[i] = temp & gesture_mask[i]; + /* temp AND enabled + * disable the gestures that are specified and + * previously enabled */ + } + + pointer = gesture_mask; + } else { + i = 0; /* if NULL is passed disable all the possible + * gestures */ + pointer = (u8 *)&i; + } + + res = setFeatures(FEAT_SEL_GESTURE, pointer, GESTURE_MASK_SIZE); + if (res < OK) { + pr_err("disableGesture: ERROR %08X\n", res); + goto END; + } + + pr_info("disableGesture DONE!\n"); + + res = OK; + +END: + mutex_unlock(&gestureMask_mutex); + return res; + } else { + pr_err("disableGesture: Size not valid! %d > %d ERROR %08X\n", + size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Perform all the steps required to put the chip in gesture mode + * @param reload if set to 1, before entering in gesture mode it will re-enable + * in the FW the last defined gesture mask + * @return OK if success or an error code which specify the type of error + */ +int enterGestureMode(int reload) +{ + int res, ret; + + res = fts_disableInterrupt(); + if (res < OK) { + pr_err("enterGestureMode: ERROR %08X\n", + res | ERROR_DISABLE_INTER); + return res | ERROR_DISABLE_INTER; + } + + if (reload == 1 || refreshGestureMask == 1) { + res = enableGesture(NULL, 0); + if (res < OK) { + pr_err("enterGestureMode: enableGesture ERROR %08X\n", + res); + goto END; + } + + refreshGestureMask = 0; + } + + res = setScanMode(SCAN_MODE_LOW_POWER, 0); + if (res < OK) { + pr_err("enterGestureMode: enter gesture mode ERROR %08X\n", + res); + goto END; + } + + res = OK; +END: + ret = fts_enableInterrupt(); + if (ret < OK) { + pr_err("enterGestureMode: fts_enableInterrupt ERROR %08X\n", + res | ERROR_ENABLE_INTER); + res |= ret | ERROR_ENABLE_INTER; + } + + + return res; +} + +/** + * Check if one or more Gesture IDs are currently enabled in gesture_mask + * @return FEAT_ENABLE if one or more gesture ids are enabled, FEAT_DISABLE if + * all the gesture ids are currently disabled + */ +int isAnyGestureActive(void) +{ + int res = 0; + + while (res < (GESTURE_MASK_SIZE - 1) && gesture_mask[res] == 0) + /* -1 because in any case the last gesture mask byte will + * be evaluated with the following if */ + res++; + + if (gesture_mask[res] != 0) { + pr_info("%s: Active Gestures Found! gesture_mask[%d] = %02X !\n", + __func__, res, gesture_mask[res]); + return FEAT_ENABLE; + } else { + pr_info("%s: All Gestures Disabled!\n", __func__); + return FEAT_DISABLE; + } +} + + +/** + * Read from the frame buffer the gesture coordinates pairs of the points draw + * by an user when a gesture is detected + * @param event pointer to a byte array which contains the gesture event + * reported + * by the fw when a gesture is detected + * @return OK if success or an error code which specify the type of error + */ +int readGestureCoords(u8 *event) +{ + int i = 0; + u64 address = 0; + int res; + + u8 val[GESTURE_MAX_COORDS_PAIRS_REPORT * 4]; + + /* the max coordinates to read are GESTURE_COORDS_REPORT_MAX*4 + * (because each coordinate is a short(*2) and we have x and y) */ + + + if (event[0] == EVT_ID_USER_REPORT && + event[1] == EVT_TYPE_USER_GESTURE) { + address = (event[4] << 8) | event[3]; /* Offset in framebuff */ + gesture_coords_reported = event[5]; /* number of pairs + * coords reported */ + if (gesture_coords_reported > GESTURE_MAX_COORDS_PAIRS_REPORT) { + pr_err("%s: FW reported more than %d points for the gestures! Decreasing to %d\n", + __func__, gesture_coords_reported, + GESTURE_MAX_COORDS_PAIRS_REPORT); + gesture_coords_reported = + GESTURE_MAX_COORDS_PAIRS_REPORT; + } + + pr_info("%s: Offset: %llx , coords pairs = %d\n", + __func__, address, gesture_coords_reported); + + res = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, + val, (gesture_coords_reported * 2 * 2), + DUMMY_FRAMEBUFFER); + /* *2 because each coord is made by 2 bytes, + * *2 because there are x and y */ + if (res < OK) { + pr_err("%s: Cannot read the coordinates! ERROR %08X\n", + __func__, res); + gesture_coords_reported = ERROR_OP_NOT_ALLOW; + return res; + } + + /* all the points of the gesture are stored in val */ + for (i = 0; i < gesture_coords_reported; i++) { + gesture_coordinates_x[i] = + (((u16)val[i * 2 + 1]) & 0x0F) << 8 | + (((u16)val[i * 2]) & 0xFF); + gesture_coordinates_y[i] = + (((u16)val[gesture_coords_reported * + 2 + i * 2 + 1]) & 0x0F) << 8 | + (((u16)val[gesture_coords_reported * + 2 + i * 2]) & 0xFF); + } + + + pr_info("%s: Reading Gesture Coordinates DONE!\n", __func__); + return OK; + } else { + pr_err("%s: The event passsed as argument is invalid! ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Return the coordinates of the points stored during the last detected gesture + * @param x output parameter which will store the address of the array + * containing the x coordinates + * @param y output parameter which will store the address of the array + * containing the y coordinates + * @return the number of points (x,y) stored and therefore the size of the x + * and y array returned. + */ +int getGestureCoords(u16 **x, u16 **y) +{ + *x = gesture_coordinates_x; + *y = gesture_coordinates_y; + pr_info("%s: Number of gesture coordinates pairs returned = %d\n", + __func__, gesture_coords_reported); + return gesture_coords_reported; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsGesture.h b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.h new file mode 100644 index 000000000000..cb59737f76a9 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.h @@ -0,0 +1,47 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Gesture Utilities * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsGesture.h + * \brief Contains all the macro and prototypes to handle the Gesture Detection + * features + */ + + +#ifndef FTS_GESTURE_H_ +#define FTS_GESTURE_H_ + + + + +#include "ftsHardware.h" + +#define GESTURE_MASK_SIZE 4 /* /< number of bytes of the + * gesture mask */ + +#define GESTURE_MAX_COORDS_PAIRS_REPORT 100 /* /< max number of gestures + * coordinates pairs reported */ + + + +int updateGestureMask(u8 *mask, int size, int en); +int disableGesture(u8 *mask, int size); +int enableGesture(u8 *mask, int size); +int enterGestureMode(int reload); +int isAnyGestureActive(void); +int readGestureCoords(u8 *event); +int getGestureCoords(u16 **x, u16 **y); + +#endif /* ! _GESTURE_H_ */ diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsHardware.h b/drivers/input/touchscreen/stm/fts_lib/ftsHardware.h new file mode 100644 index 000000000000..845da2b711b2 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsHardware.h @@ -0,0 +1,282 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * HW related data * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsHardware.h + * \brief Contains all the definitions and information related to the IC + * from an hardware point of view + */ + +#ifndef FTS_HARDWARE_H +#define FTS_HARDWARE_H + +/* DIGITAL CHIP INFO */ +#define DCHIP_ID_0 0x36 /* /< LSB chip ID for FTM5 */ +#define DCHIP_ID_1 0x39 /* /< MSB chip ID for FTM5 */ + +#define DCHIP_FW_VER_BYTE 2 /* /< number of bytes of the fw + * versions */ + +/* CHUNKS */ +#define READ_CHUNK 1024 /* /< chunk dimension of + * a single i2c read, + * max allowed value is 2kB */ +#define WRITE_CHUNK 1024 /* /< chunk dimension of + * a single i2c write, + * max allowed value is 2kB */ +#define MEMORY_CHUNK 1024 /* /< chunk dimenasion of + * a single i2c write on mem, + * max allowed value is 2kB */ + +/* PROTOCOL INFO */ +#define I2C_INTERFACE /* /< comment if the chip use SPI bus */ +#ifdef I2C_INTERFACE +#define I2C_SAD 0x49 /* /< slave address of the IC */ +#else +#define SPI4_WIRE /* /< comment if the master is SPI3 + * wires + * (MOSI and MISO share same line) */ +#define SPI_DELAY_CS 10 /* /< time in usec to wait + * before rising the CS */ +#define SPI_CLOCK_FREQ 7000000 /* /< clock frequency in Hz of + * the SPI bus */ +#endif + +#define IER_ENABLE 0x41 /* /< value to write in IER_ADDR + * to enable the interrupts */ +#define IER_DISABLE 0x00 /* /< value to write in IER_ADDR + * to disable the interrupts + **/ + +/* FLASH COMMAND */ +/** @defgroup flash_command Flash Commands + * All the commands that works with the flash of the IC + * @{ + */ +#define FLASH_CMD_UNLOCK 0xF7 + +#define FLASH_CMD_READ_REGISTER 0xFA +#define FLASH_CMD_WRITE_REGISTER 0xFA + +/* FLASH UNLOCK PARAMETER */ +#define FLASH_UNLOCK_CODE0 0x25 +#define FLASH_UNLOCK_CODE1 0x20 + +/* FLASH ERASE and DMA PARAMETER */ +#define FLASH_ERASE_START 0x80 +#define FLASH_ERASE_CODE1 0xC0 +#define FLASH_DMA_CODE1 0xC0 +#define FLASH_ERASE_UNLOCK_CODE0 0xDE +#define FLASH_ERASE_UNLOCK_CODE1 0x03 +#define FLASH_ERASE_CODE0 0x6A +#define FLASH_DMA_CODE0 0x71 +#define FLASH_DMA_CONFIG 0x72 +#define FLASH_NUM_PAGE 32 /* /< number of pages in main + * flash */ +#define FLASH_CX_PAGE_START 28 /* /< starting page which + * contain Cx data */ +#define FLASH_CX_PAGE_END 30 /* /< last page which contain Cx + * data */ +#define FLASH_PANEL_PAGE_START 26 /* /< starting page which + * contain Panel Init data */ +#define FLASH_PANEL_PAGE_END 27 /* /< last page which contain + * Panel Init data */ +/** @} */ + +/* FLASH ADDRESS */ +#define FLASH_ADDR_CODE 0x00000000 /* /< address of code in + * FTI */ +#define FLASH_ADDR_CONFIG 0x00007C00 /* /< address of config + * in FTI */ +#define FLASH_ADDR_CX 0x00007000 /* /< address of Init + * data in FTI */ + +/* SIZES FW, CODE, CONFIG, MEMH */ +/** @defgroup fw_file FW file info + * All the info related to the fw file + * @{ + */ +#define FW_HEADER_SIZE 64 /* /< dimension of the header in + * .fts file */ +#define FW_HEADER_SIGNATURE 0xAA55AA55 /* /< header signature + * */ +#define FW_FTB_VER 0x00000001 /* /< .ftb version */ +#define FW_BYTES_ALIGN 4 /* /< allignment of the info */ +#define FW_BIN_VER_OFFSET 16 /* /< offset of the fw version + * in the .ftb file */ +#define FW_BIN_CONFIG_ID_OFFSET 20 /* /< offset of the config id in + * the .ftb file */ +#define FW_CX_VERSION (16 + 4)/* CX version offset in sec2 of + * FW */ +/** @} */ + +/* FIFO */ +#define FIFO_EVENT_SIZE 8 /* /< number of bytes of one + * event */ +#define FIFO_DEPTH 32 /* /< max number of events that + * the FIFO can collect before + * going in overflow in FTM5 */ + +#ifdef I2C_INTERFACE +#define FIFO_CMD_READALL 0x86 /* /< command to read all + * the events in the FIFO */ +#else +#define FIFO_CMD_READALL 0x87 /* /< command to read all + * the events in the FIFO */ +#endif +#define FIFO_CMD_READONE FIFO_CMD_READALL/* /< commad to read + * one event from FIFO + **/ + + +/* OP CODES FOR MEMORY (based on protocol) */ +#ifdef I2C_INTERFACE +#define FTS_CMD_HW_REG_R 0xFA /* /< command to read an hw register if + * FTI */ +#define FTS_CMD_HW_REG_W 0xFA /* /< command to write an hw register if + * FTI */ +#define FTS_CMD_FRAMEBUFFER_R 0xA6 /* /< command to read the framebuffer if + * FTI */ +#define FTS_CMD_CONFIG_R 0xA8 /* /< command to read the config memory + * if FTI */ +#define FTS_CMD_CONFIG_W 0xA8 /* /< command to write the config memory + * if FTI */ +#else +#define FTS_CMD_HW_REG_R 0xFB /* /< command to read an hw register if + * FTI */ +#define FTS_CMD_HW_REG_W 0xFA /* /< command to write an hw register if + * FTI */ +#define FTS_CMD_FRAMEBUFFER_R 0xA7 /* /< command to read the framebuffer if + * FTI */ +#define FTS_CMD_CONFIG_R 0xA9 /* /< command to read the config memory + * if FTI */ +#define FTS_CMD_CONFIG_W 0xA8 /* /< command to write the config memory + * if FTI */ +#endif + +/* DUMMY BYTES DATA */ +#ifndef I2C_INTERFACE +#define DUMMY_HW_REG 1 /* /< 1 if the first byte read from HW + * register is dummy */ +#define DUMMY_FRAMEBUFFER 1 /* /< 1 if the first byte read from + * Frame buffer is dummy */ +#define DUMMY_CONFIG 1 /* /< 1 if the first byte read from + * Config Memory is dummy */ +#define DUMMY_FIFO 1 /* /< 1 if the first byte read from FIFO + * is dummy */ +#else +#define DUMMY_HW_REG 0 /* /< 1 if the first byte read from HW + * register is dummy */ +#define DUMMY_FRAMEBUFFER 0 /* /< 1 if the first byte read from + * Frame buffer is dummy */ +#define DUMMY_CONFIG 0 /* /< 1 if the first byte read from + * Config Memory is dummy */ +#define DUMMY_FIFO 0 /* /< 1 if the first byte read from FIFO + * is dummy */ +#endif + +/** @defgroup hw_adr HW Address + * @ingroup address + * Important addresses of hardware registers (and sometimes their important + * values) + * @{ + */ + +/* IMPORTANT HW ADDRESSES (u64) */ +#define ADDR_FRAMEBUFFER ((u64)0x0000000000000000) /* /< frame + * buffer + * address in + * memory */ +#define ADDR_ERROR_DUMP ((u64)0x000000000000EF80) /* /< start + * address dump + * error log */ + +/* SYSTEM RESET INFO */ +#define ADDR_SYSTEM_RESET ((u64)0x0000000020000024) /* /< address of + * System + * control + * register in + * FTI */ +/* value to write in SYSTEM_RESET_ADDRESS to perform a system reset in FTM5 */ +#define SYSTEM_RESET_VALUE 0x80 + + +/* REMAP REGISTER */ +#define ADDR_BOOT_OPTION ((u64)0x0000000020000025) /* /< address of + * Boot option + * register */ + +/* INTERRUPT INFO */ +#define ADDR_IER ((u64)0x0000000020000029) /* /< address of + * the Interrupt + * enable + * register in + * FTMI */ + +/* Chip ID/Fw Version */ +#define ADDR_DCHIP_ID ((u64)0x0000000020000000) /* /< chip id + * address for + * FTI */ +#define ADDR_DCHIP_FW_VER ((u64)0x0000000020000004) /* /< fw version + * address for + * FTI */ + +/* INTERFACE REGISTER */ +#define ADDR_ICR ((u64)0x000000002000002D) /* /< address of + * Device + * control + * register + * to set the + * communication + * protocol + * (SPI/I2C) */ + +#define SPI4_MASK 0x02 /* /< bit to set spi4 */ + +/* CRC ADDR */ +#define ADDR_CRC ((u64)0x0000000020000078) /* /< address of + * the CRC + * control + * register in + * FTI */ +#define CRC_MASK 0x03 /* /< bitmask which reveal if + * there is a CRC error in the flash */ + +#define ADDR_CONFIG_OFFSET ((u64)0x0000000000000000) /* /< config + * address in + * memory if FTI + * */ + +#define ADDR_GPIO_INPUT ((u64)0x0000000020000030) /* /< address of + * GPIO input + * register */ +#define ADDR_GPIO_DIRECTION ((u64)0x0000000020000032) /* /< address of + * GPIO + * direction + * register */ +#define ADDR_GPIO_PULLUP ((u64)0x0000000020000034) /* /< address of + * GPIO pullup + * register */ +#define ADDR_GPIO_CONFIG_REG0 ((u64)0x000000002000003D) /* /< address of + * GPIO config + * register */ +#define ADDR_GPIO_CONFIG_REG2 ((u64)0x000000002000003F) /* /< address of + * GPIO config + * register */ + +/**@}*/ + + +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsIO.c b/drivers/input/touchscreen/stm/fts_lib/ftsIO.c new file mode 100644 index 000000000000..9443fdd6fb4a --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsIO.c @@ -0,0 +1,924 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * I2C/SPI Communication * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsIO.c + * \brief Contains all the functions which handle with the I2C/SPI + *communication + */ + + +#include "ftsSoftware.h" + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/delay.h> +#include <linux/ctype.h> +#include <linux/of_gpio.h> + +#ifdef I2C_INTERFACE +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +static u16 I2CSAD; /* /< slave address of the IC in the i2c bus */ +#else +#include <linux/spi/spidev.h> +#endif + +static void *client; /* /< bus client retrived by the OS and + * used to execute the bus transfers */ + + + +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsHardware.h" +#include "ftsIO.h" + + +/** + * Initialize the static client variable of the fts_lib library in order + * to allow any i2c/spi transaction in the driver (Must be called in the probe) + * @param clt pointer to i2c_client or spi_device struct which identify the bus + * slave device + * @return OK + */ +int openChannel(void *clt) +{ + client = clt; +#ifdef I2C_INTERFACE + I2CSAD = ((struct i2c_client *)clt)->addr; + pr_info("openChannel: SAD: %02X\n", I2CSAD); +#else + pr_info("%s: spi_master: flags = %04X !\n", __func__, + ((struct spi_device *)client)->master->flags); + pr_info("%s: spi_device: max_speed = %d chip select = %02X bits_per_words = %d mode = %04X !\n", + __func__, ((struct spi_device *)client)->max_speed_hz, + ((struct spi_device *)client)->chip_select, + ((struct spi_device *)client)->bits_per_word, + ((struct spi_device *)client)->mode); + pr_info("openChannel: completed!\n"); +#endif + return OK; +} + +#ifdef I2C_INTERFACE +/** + * Change the I2C slave address which will be used during the transaction + * (For Debug Only) + * @param sad new slave address id + * @return OK + */ +int changeSAD(u8 sad) +{ + I2CSAD = sad; + return OK; +} +#endif + + +/** + * Retrieve the pointer to the device struct of the IC + * @return a the device struct pointer if client was previously set + * or NULL in all the other cases + */ +struct device *getDev(void) +{ + if (client != NULL) + return &(getClient()->dev); + else + return NULL; +} + + +#ifdef I2C_INTERFACE +/** + * Retrieve the pointer of the i2c_client struct representing the IC as i2c + * slave + * @return client if it was previously set or NULL in all the other cases + */ +struct i2c_client *getClient() +{ + if (client != NULL) + return (struct i2c_client *)client; + else + return NULL; +} +#else +/** + * Retrieve the pointer of the spi_device struct representing the IC as spi + * slave + * @return client if it was previously set or NULL in all the other cases + */ +struct spi_device *getClient() +{ + if (client != NULL) + return (struct spi_device *)client; + else + return NULL; +} +#endif + +struct fts_ts_info *getDrvInfo(void) +{ + struct device *dev = getDev(); + struct fts_ts_info *info = NULL; + + if (dev != NULL) + info = dev_get_drvdata(dev); + return info; +} + +/****************** New I2C API *********************/ + +/** + * Perform a direct bus read + * @param outBuf pointer of a byte array which should contain the byte read + * from the IC + * @param byteToRead number of bytes to read + * @return OK if success or an error code which specify the type of error + */ +static int fts_read_internal(u8 *outBuf, int byteToRead, bool dma_safe) +{ + int ret = -1; + int retry = 0; + struct fts_ts_info *info = getDrvInfo(); +#ifdef I2C_INTERFACE + struct i2c_msg I2CMsg[1]; +#else + struct spi_message msg; + struct spi_transfer transfer[1] = { { 0 } }; +#endif + + if (dma_safe == false && byteToRead > sizeof(info->io_read_buf)) { + pr_err("%s: preallocated buffers are too small!\n", __func__); + return ERROR_ALLOC; + } + +#ifdef I2C_INTERFACE + I2CMsg[0].addr = (__u16)I2CSAD; + I2CMsg[0].flags = (__u16)I2C_M_RD; + I2CMsg[0].len = (__u16)byteToRead; + if (dma_safe == false) + I2CMsg[0].buf = (__u8 *)info->io_read_buf; + else + I2CMsg[0].buf = (__u8 *)outBuf; +#else + spi_message_init(&msg); + + transfer[0].len = byteToRead; + transfer[0].delay_usecs = SPI_DELAY_CS; + transfer[0].tx_buf = NULL; + if (dma_safe == false) + transfer[0].rx_buf = info->io_read_buf; + else + transfer[0].rx_buf = outBuf; + spi_message_add_tail(&transfer[0], &msg); +#endif + + if (client == NULL) + return ERROR_BUS_O; + while (retry < I2C_RETRY && ret < OK) { +#ifdef I2C_INTERFACE + ret = i2c_transfer(getClient()->adapter, I2CMsg, 1); +#else + ret = spi_sync(getClient(), &msg); +#endif + + retry++; + if (ret < OK) + mdelay(I2C_WAIT_BEFORE_RETRY); + /* pr_err("fts_writeCmd: attempt %d\n", retry); */ + } + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_R); + return ERROR_BUS_R; + } + + if (dma_safe == false) + memcpy(outBuf, info->io_read_buf, byteToRead); + + return OK; +} + + +/** + * Perform a bus write followed by a bus read without a stop condition + * @param cmd byte array containing the command to write + * @param cmdLength size of cmd + * @param outBuf pointer of a byte array which should contain the bytes read + * from the IC + * @param byteToRead number of bytes to read + * @return OK if success or an error code which specify the type of error + */ +static int fts_writeRead_internal(u8 *cmd, int cmdLength, u8 *outBuf, + int byteToRead, bool dma_safe) +{ + int ret = -1; + int retry = 0; + struct fts_ts_info *info = getDrvInfo(); +#ifdef I2C_INTERFACE + struct i2c_msg I2CMsg[2]; +#else + struct spi_message msg; + struct spi_transfer transfer[2] = { { 0 }, { 0 } }; +#endif + + if (dma_safe == false && (cmdLength > sizeof(info->io_write_buf) || + byteToRead > sizeof(info->io_read_buf))) { + pr_err("%s: preallocated buffers are too small!\n", __func__); + return ERROR_ALLOC; + } + +#ifdef I2C_INTERFACE + if (dma_safe == false) { + memcpy(info->io_write_buf, cmd, cmdLength); + cmd = info->io_write_buf; + } + + /* write msg */ + I2CMsg[0].addr = (__u16)I2CSAD; + I2CMsg[0].flags = (__u16)0; + I2CMsg[0].len = (__u16)cmdLength; + I2CMsg[0].buf = (__u8 *)cmd; + + /* read msg */ + I2CMsg[1].addr = (__u16)I2CSAD; + I2CMsg[1].flags = I2C_M_RD; + I2CMsg[1].len = byteToRead; + if (dma_safe == false) + I2CMsg[1].buf = (__u8 *)info->io_read_buf; + else + I2CMsg[1].buf = (__u8 *)outBuf; +#else + if (dma_safe == false) { + memcpy(info->io_write_buf, cmd, cmdLength); + cmd = info->io_write_buf; + } + + spi_message_init(&msg); + + transfer[0].len = cmdLength; + transfer[0].tx_buf = cmd; + transfer[0].rx_buf = NULL; + spi_message_add_tail(&transfer[0], &msg); + + transfer[1].len = byteToRead; + transfer[1].delay_usecs = SPI_DELAY_CS; + transfer[1].tx_buf = NULL; + if (dma_safe == false) + transfer[1].rx_buf = info->io_read_buf; + else + transfer[1].rx_buf = outBuf; + spi_message_add_tail(&transfer[1], &msg); + +#endif + + if (client == NULL) + return ERROR_BUS_O; + + while (retry < I2C_RETRY && ret < OK) { +#ifdef I2C_INTERFACE + ret = i2c_transfer(getClient()->adapter, I2CMsg, 2); +#else + ret = spi_sync(getClient(), &msg); +#endif + + retry++; + if (ret < OK) + mdelay(I2C_WAIT_BEFORE_RETRY); + } + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_WR); + return ERROR_BUS_WR; + } + + if (dma_safe == false) + memcpy(outBuf, info->io_read_buf, byteToRead); + + return OK; +} + + +/** + * Perform a bus write + * @param cmd byte array containing the command to write + * @param cmdLength size of cmd + * @return OK if success or an error code which specify the type of error + */ +static int fts_write_internal(u8 *cmd, int cmdLength, bool dma_safe) +{ + int ret = -1; + int retry = 0; + struct fts_ts_info *info = getDrvInfo(); +#ifdef I2C_INTERFACE + struct i2c_msg I2CMsg[1]; +#else + struct spi_message msg; + struct spi_transfer transfer[1] = { { 0 } }; +#endif + + if (dma_safe == false && cmdLength > sizeof(info->io_write_buf)) { + pr_err("%s: preallocated buffers are too small!\n", __func__); + return ERROR_ALLOC; + } + +#ifdef I2C_INTERFACE + if (dma_safe == false) { + memcpy(info->io_write_buf, cmd, cmdLength); + cmd = info->io_write_buf; + } + + I2CMsg[0].addr = (__u16)I2CSAD; + I2CMsg[0].flags = (__u16)0; + I2CMsg[0].len = (__u16)cmdLength; + I2CMsg[0].buf = (__u8 *)cmd; +#else + if (dma_safe == false) { + memcpy(info->io_write_buf, cmd, cmdLength); + cmd = info->io_write_buf; + } + + spi_message_init(&msg); + + transfer[0].len = cmdLength; + transfer[0].delay_usecs = SPI_DELAY_CS; + transfer[0].tx_buf = cmd; + transfer[0].rx_buf = NULL; + spi_message_add_tail(&transfer[0], &msg); +#endif + + + if (client == NULL) + return ERROR_BUS_O; + while (retry < I2C_RETRY && ret < OK) { +#ifdef I2C_INTERFACE + ret = i2c_transfer(getClient()->adapter, I2CMsg, 1); +#else + ret = spi_sync(getClient(), &msg); +#endif + + retry++; + if (ret < OK) + mdelay(I2C_WAIT_BEFORE_RETRY); + /* pr_err("fts_writeCmd: attempt %d\n", retry); */ + } + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_W); + return ERROR_BUS_W; + } + return OK; +} + +/** + * Write a FW command to the IC and check automatically the echo event + * @param cmd byte array containing the command to send + * @param cmdLength size of cmd + * @return OK if success, or an error code which specify the type of error + */ +static int fts_writeFwCmd_internal(u8 *cmd, int cmdLength, bool dma_safe) +{ + int ret = -1; + int ret2 = -1; + int retry = 0; + struct fts_ts_info *info = getDrvInfo(); +#ifdef I2C_INTERFACE + struct i2c_msg I2CMsg[1]; +#else + struct spi_message msg; + struct spi_transfer transfer[1] = { { 0 } }; +#endif + + if (dma_safe == false && cmdLength > sizeof(info->io_write_buf)) { + pr_err("%s: preallocated buffers are too small!\n", __func__); + return ERROR_ALLOC; + } + +#ifdef I2C_INTERFACE + if (dma_safe == false) { + memcpy(info->io_write_buf, cmd, cmdLength); + cmd = info->io_write_buf; + } + + I2CMsg[0].addr = (__u16)I2CSAD; + I2CMsg[0].flags = (__u16)0; + I2CMsg[0].len = (__u16)cmdLength; + I2CMsg[0].buf = (__u8 *)cmd; +#else + if (dma_safe == false) { + memcpy(info->io_write_buf, cmd, cmdLength); + cmd = info->io_write_buf; + } + + spi_message_init(&msg); + + transfer[0].len = cmdLength; + transfer[0].delay_usecs = SPI_DELAY_CS; + transfer[0].tx_buf = cmd; + transfer[0].rx_buf = NULL; + spi_message_add_tail(&transfer[0], &msg); +#endif + + if (client == NULL) + return ERROR_BUS_O; + resetErrorList(); + while (retry < I2C_RETRY && (ret < OK || ret2 < OK)) { +#ifdef I2C_INTERFACE + ret = i2c_transfer(getClient()->adapter, I2CMsg, 1); +#else + ret = spi_sync(getClient(), &msg); +#endif + retry++; + if (ret >= 0) + ret2 = checkEcho(cmd, cmdLength); + if (ret < OK || ret2 < OK) + mdelay(I2C_WAIT_BEFORE_RETRY); + /* pr_err("fts_writeCmd: attempt %d\n", retry); */ + } + if (ret < 0) { + pr_err("fts_writeFwCmd: ERROR %08X\n", ERROR_BUS_W); + return ERROR_BUS_W; + } + if (ret2 < OK) { + pr_err("fts_writeFwCmd: check echo ERROR %08X\n", ret2); + return ret2; + } + return OK; +} + + +/** + * Perform two bus write and one bus read without any stop condition + * In case of FTI this function is not supported and the same sequence + * can be achieved calling fts_write followed by an fts_writeRead. + * @param writeCmd1 byte array containing the first command to write + * @param writeCmdLength size of writeCmd1 + * @param readCmd1 byte array containing the second command to write + * @param readCmdLength size of readCmd1 + * @param outBuf pointer of a byte array which should contain the bytes read + * from the IC + * @param byteToRead number of bytes to read + * @return OK if success or an error code which specify the type of error + */ +static int fts_writeThenWriteRead_internal(u8 *writeCmd1, int writeCmdLength, + u8 *readCmd1, int readCmdLength, + u8 *outBuf, int byteToRead, + bool dma_safe) +{ + int ret = -1; + int retry = 0; + struct fts_ts_info *info = getDrvInfo(); +#ifdef I2C_INTERFACE + struct i2c_msg I2CMsg[3]; +#else + struct spi_message msg; + struct spi_transfer transfer[3] = { { 0 }, { 0 }, { 0 } }; +#endif + + if (dma_safe == false && (writeCmdLength > sizeof(info->io_write_buf) || + readCmdLength > sizeof(info->io_extra_write_buf) || + byteToRead > sizeof(info->io_read_buf))) { + pr_err("%s: preallocated buffers are too small!\n", __func__); + return ERROR_ALLOC; + } + +#ifdef I2C_INTERFACE + if (dma_safe == false) { + memcpy(info->io_write_buf, writeCmd1, writeCmdLength); + writeCmd1 = info->io_write_buf; + memcpy(info->io_extra_write_buf, readCmd1, readCmdLength); + readCmd1 = info->io_extra_write_buf; + } + + /* write msg */ + I2CMsg[0].addr = (__u16)I2CSAD; + I2CMsg[0].flags = (__u16)0; + I2CMsg[0].len = (__u16)writeCmdLength; + I2CMsg[0].buf = (__u8 *)writeCmd1; + + /* write msg */ + I2CMsg[1].addr = (__u16)I2CSAD; + I2CMsg[1].flags = (__u16)0; + I2CMsg[1].len = (__u16)readCmdLength; + I2CMsg[1].buf = (__u8 *)readCmd1; + + /* read msg */ + I2CMsg[2].addr = (__u16)I2CSAD; + I2CMsg[2].flags = I2C_M_RD; + I2CMsg[2].len = byteToRead; + if (dma_safe == false) + I2CMsg[2].buf = (__u8 *)info->io_read_buf; + else + I2CMsg[2].buf = (__u8 *)outBuf; +#else + if (dma_safe == false) { + memcpy(info->io_write_buf, writeCmd1, writeCmdLength); + writeCmd1 = info->io_write_buf; + memcpy(info->io_extra_write_buf, readCmd1, readCmdLength); + readCmd1 = info->io_extra_write_buf; + } + + spi_message_init(&msg); + + transfer[0].len = writeCmdLength; + transfer[0].tx_buf = writeCmd1; + transfer[0].rx_buf = NULL; + spi_message_add_tail(&transfer[0], &msg); + + transfer[1].len = readCmdLength; + transfer[1].tx_buf = readCmd1; + transfer[1].rx_buf = NULL; + spi_message_add_tail(&transfer[1], &msg); + + transfer[2].len = byteToRead; + transfer[2].delay_usecs = SPI_DELAY_CS; + transfer[2].tx_buf = NULL; + if (dma_safe == false) + transfer[2].rx_buf = info->io_read_buf; + else + transfer[2].rx_buf = outBuf; + spi_message_add_tail(&transfer[2], &msg); +#endif + + if (client == NULL) + return ERROR_BUS_O; + while (retry < I2C_RETRY && ret < OK) { +#ifdef I2C_INTERFACE + ret = i2c_transfer(getClient()->adapter, I2CMsg, 3); +#else + ret = spi_sync(getClient(), &msg); +#endif + retry++; + if (ret < OK) + mdelay(I2C_WAIT_BEFORE_RETRY); + } + + if (ret < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_WR); + return ERROR_BUS_WR; + } + + if (dma_safe == false) + memcpy(outBuf, info->io_read_buf, byteToRead); + + return OK; +} + +/* Wrapper API for i2c read and write */ +int fts_read(u8 *outBuf, int byteToRead) +{ + return fts_read_internal(outBuf, byteToRead, false); +} + +int fts_read_heap(u8 *outBuf, int byteToRead) +{ + return fts_read_internal(outBuf, byteToRead, true); +} + +int fts_writeRead(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead) +{ + return fts_writeRead_internal(cmd, cmdLength, outBuf, byteToRead, + false); +} + +int fts_writeRead_heap(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead) +{ + return fts_writeRead_internal(cmd, cmdLength, outBuf, byteToRead, true); +} + +int fts_write(u8 *cmd, int cmdLength) +{ + return fts_write_internal(cmd, cmdLength, false); +} + +int fts_write_heap(u8 *cmd, int cmdLength) +{ + return fts_write_internal(cmd, cmdLength, true); +} + +int fts_writeFwCmd(u8 *cmd, int cmdLength) +{ + return fts_writeFwCmd_internal(cmd, cmdLength, false); +} + +int fts_writeFwCmd_heap(u8 *cmd, int cmdLength) +{ + return fts_writeFwCmd_internal(cmd, cmdLength, true); +} + +int fts_writeThenWriteRead(u8 *writeCmd1, int writeCmdLength, + u8 *readCmd1, int readCmdLength, + u8 *outBuf, int byteToRead) +{ + return fts_writeThenWriteRead_internal(writeCmd1, writeCmdLength, + readCmd1, readCmdLength, + outBuf, byteToRead, false); +} + +int fts_writeThenWriteRead_heap(u8 *writeCmd1, int writeCmdLength, + u8 *readCmd1, int readCmdLength, + u8 *outBuf, int byteToRead) +{ + return fts_writeThenWriteRead_internal(writeCmd1, writeCmdLength, + readCmd1, readCmdLength, + outBuf, byteToRead, true); +} + +/** + * Perform a chunked write with one byte op code and 1 to 8 bytes address + * @param cmd byte containing the op code to write + * @param addrSize address size in byte + * @param address the starting address + * @param data pointer of a byte array which contain the bytes to write + * @param dataSize size of data + * @return OK if success or an error code which specify the type of error + */ +/* this function works only if the address is max 8 bytes */ +int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data, + int dataSize) +{ + u8 *finalCmd; + int remaining = dataSize; + int toWrite = 0, i = 0; + struct fts_ts_info *info = getDrvInfo(); + + finalCmd = info->io_write_buf; + + if (addrSize <= sizeof(u64)) { + while (remaining > 0) { + if (remaining >= WRITE_CHUNK) { + toWrite = WRITE_CHUNK; + remaining -= WRITE_CHUNK; + } else { + toWrite = remaining; + remaining = 0; + } + + finalCmd[0] = cmd; + pr_debug("%s: addrSize = %d\n", __func__, addrSize); + for (i = 0; i < addrSize; i++) { + finalCmd[i + 1] = (u8)((address >> ((addrSize - + 1 - i) * + 8)) & 0xFF); + pr_debug("%s: cmd[%d] = %02X\n", + __func__, i + 1, finalCmd[i + 1]); + } + + memcpy(&finalCmd[addrSize + 1], data, toWrite); + + if (fts_write_heap(finalCmd, 1 + addrSize + toWrite) + < OK) { + pr_err(" %s: ERROR %08X\n", + __func__, ERROR_BUS_W); + return ERROR_BUS_W; + } + + address += toWrite; + + data += toWrite; + } + } else + pr_err("%s: address size bigger than max allowed %lu... ERROR %08X\n", + __func__, sizeof(u64), ERROR_OP_NOT_ALLOW); + + return OK; +} + +/** + * Perform a chunked write read with one byte op code and 1 to 8 bytes address + * and dummy byte support. + * @param cmd byte containing the op code to write + * @param addrSize address size in byte + * @param address the starting address + * @param outBuf pointer of a byte array which contain the bytes to read + * @param byteToRead number of bytes to read + * @param hasDummyByte if the first byte of each reading is dummy (must be + * skipped) + * set to 1, otherwise if it is valid set to 0 (or any other value) + * @return OK if success or an error code which specify the type of error + */ +int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, + int byteToRead, int hasDummyByte) +{ + u8 *finalCmd; + u8 *buff; + int remaining = byteToRead; + int toRead = 0, i = 0; + struct fts_ts_info *info = getDrvInfo(); + + finalCmd = info->io_write_buf; + buff = info->io_read_buf; + + while (remaining > 0) { + if (remaining >= READ_CHUNK) { + toRead = READ_CHUNK; + remaining -= READ_CHUNK; + } else { + toRead = remaining; + remaining = 0; + } + + finalCmd[0] = cmd; + for (i = 0; i < addrSize; i++) + finalCmd[i + 1] = (u8)((address >> ((addrSize - 1 - i) * + 8)) & 0xFF); + + if (hasDummyByte == 1) { + if (fts_writeRead_heap(finalCmd, 1 + addrSize, buff, + toRead + 1) < OK) { + pr_err("%s: read error... ERROR %08X\n", + __func__, ERROR_BUS_WR); + return ERROR_BUS_WR; + } + memcpy(outBuf, buff + 1, toRead); + } else { + if (fts_writeRead_heap(finalCmd, 1 + addrSize, buff, + toRead) < OK) { + pr_err("%s: read error... ERROR %08X\n", + __func__, ERROR_BUS_WR); + return ERROR_BUS_WR; + } + memcpy(outBuf, buff, toRead); + } + + address += toRead; + + outBuf += toRead; + } + + return OK; +} + +/** + * Perform a chunked write followed by a second write with one byte op code + * for each write and 1 to 8 bytes address (the sum of the 2 address size of + * the two writes can not exceed 8 bytes) + * @param cmd1 byte containing the op code of first write + * @param addrSize1 address size in byte of first write + * @param cmd2 byte containing the op code of second write + * @param addrSize2 address size in byte of second write + * @param address the starting address + * @param data pointer of a byte array which contain the bytes to write + * @param dataSize size of data + * @return OK if success or an error code which specify the type of error + */ +/* this function works only if the sum of two addresses in the two commands is + * max 8 bytes */ +int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, + AddrSize addrSize2, u64 address, u8 *data, + int dataSize) +{ + u8 *finalCmd1; + u8 *finalCmd2; + int remaining = dataSize; + int toWrite = 0, i = 0; + struct fts_ts_info *info = getDrvInfo(); + + finalCmd1 = info->io_write_buf; + finalCmd2 = info->io_extra_write_buf; + + while (remaining > 0) { + if (remaining >= WRITE_CHUNK) { + toWrite = WRITE_CHUNK; + remaining -= WRITE_CHUNK; + } else { + toWrite = remaining; + remaining = 0; + } + + finalCmd1[0] = cmd1; + for (i = 0; i < addrSize1; i++) + finalCmd1[i + 1] = (u8)((address >> ((addrSize1 + + addrSize2 - 1 - + i) * 8)) & 0xFF); + + finalCmd2[0] = cmd2; + for (i = addrSize1; i < addrSize1 + addrSize2; i++) + finalCmd2[i - addrSize1 + 1] = (u8)((address >> + ((addrSize1 + + addrSize2 - 1 - + i) * 8)) & 0xFF); + + memcpy(&finalCmd2[addrSize2 + 1], data, toWrite); + + if (fts_write_heap(finalCmd1, 1 + addrSize1) < OK) { + pr_err("%s: first write error... ERROR %08X\n", + __func__, ERROR_BUS_W); + return ERROR_BUS_W; + } + + if (fts_write_heap(finalCmd2, 1 + addrSize2 + toWrite) < OK) { + pr_err("%s: second write error... ERROR %08X\n", + __func__, ERROR_BUS_W); + return ERROR_BUS_W; + } + + address += toWrite; + + data += toWrite; + } + + return OK; +} + +/** + * Perform a chunked write followed by a write read with one byte op code + * and 1 to 8 bytes address for each write and dummy byte support. + * @param cmd1 byte containing the op code of first write + * @param addrSize1 address size in byte of first write + * @param cmd2 byte containing the op code of second write read + * @param addrSize2 address size in byte of second write read + * @param address the starting address + * @param outBuf pointer of a byte array which contain the bytes to read + * @param byteToRead number of bytes to read + * @param hasDummyByte if the first byte of each reading is dummy (must be + * skipped) set to 1, + * otherwise if it is valid set to 0 (or any other value) + * @return OK if success or an error code which specify the type of error + */ +/* this function works only if the sum of two addresses in the two commands is + * max 8 bytes */ +int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, + AddrSize addrSize2, u64 address, u8 *outBuf, + int byteToRead, int hasDummyByte) +{ + u8 *finalCmd1; + u8 *finalCmd2; + u8 *buff; + int remaining = byteToRead; + int toRead = 0, i = 0; + struct fts_ts_info *info = getDrvInfo(); + + finalCmd1 = info->io_write_buf; + finalCmd2 = info->io_extra_write_buf; + buff = info->io_read_buf; + + while (remaining > 0) { + if (remaining >= READ_CHUNK) { + toRead = READ_CHUNK; + remaining -= READ_CHUNK; + } else { + toRead = remaining; + remaining = 0; + } + + + finalCmd1[0] = cmd1; + for (i = 0; i < addrSize1; i++) + finalCmd1[i + 1] = (u8)((address >> ((addrSize1 + + addrSize2 - 1 - + i) * 8)) & 0xFF); + + finalCmd2[0] = cmd2; + for (i = addrSize1; i < addrSize1 + addrSize2; i++) + finalCmd2[i - addrSize1 + 1] = (u8)((address >> + ((addrSize1 + + addrSize2 - 1 - + i) * 8)) & 0xFF); + + if (fts_write_heap(finalCmd1, 1 + addrSize1) < OK) { + pr_err("%s: first write error... ERROR %08X\n", + __func__, ERROR_BUS_W); + return ERROR_BUS_W; + } + + if (hasDummyByte == 1) { + if (fts_writeRead_heap(finalCmd2, 1 + addrSize2, buff, + toRead + 1) < OK) { + pr_err("%s: read error... ERROR %08X\n", + __func__, ERROR_BUS_WR); + return ERROR_BUS_WR; + } + memcpy(outBuf, buff + 1, toRead); + } else { + if (fts_writeRead_heap(finalCmd2, 1 + addrSize2, buff, + toRead) < OK) { + pr_err("%s: read error... ERROR %08X\n", + __func__, ERROR_BUS_WR); + return ERROR_BUS_WR; + } + memcpy(outBuf, buff, toRead); + } + + address += toRead; + + outBuf += toRead; + } + + return OK; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsIO.h b/drivers/input/touchscreen/stm/fts_lib/ftsIO.h new file mode 100644 index 000000000000..f470991b05c2 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsIO.h @@ -0,0 +1,78 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * I2C/SPI Communication * + * * + ************************************************************************** + ************************************************************************** + * + */ +/*! + * \file ftsIO.h + * \brief Contains all the definitions and prototypes used and implemented in + * ftsIO.c + */ + +#ifndef FTS_IO_H +#define FTS_IO_H + +#include "ftsSoftware.h" + +#define I2C_RETRY 3 /* /< number of retry in case of i2c + * failure */ +#define I2C_WAIT_BEFORE_RETRY 2 /* /< wait in ms before retry an i2c + * transaction */ + +#ifdef I2C_INTERFACE +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +struct i2c_client *getClient(void); +#else +#include <linux/spi/spi.h> +struct spi_device *getClient(void); +#endif + + + +int openChannel(void *clt); +struct device *getDev(void); + + + +/*************** NEW I2C API ****************/ +int changeSAD(u8 sad); +int fts_read(u8 *outBuf, int byteToRead); +int fts_read_heap(u8 *outBuf, int byteToRead); +int fts_writeRead(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead); +int fts_writeRead_heap(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead); +int fts_write(u8 *cmd, int cmdLength); +int fts_write_heap(u8 *cmd, int cmdLength); +int fts_writeFwCmd(u8 *cmd, int cmdLength); +int fts_writeFwCmd_heap(u8 *cmd, int cmdLength); +int fts_writeThenWriteRead(u8 *writeCmd1, int writeCmdLength, + u8 *readCmd1, int readCmdLength, + u8 *outBuf, int byteToRead); +int fts_writeThenWriteRead_heap(u8 *writeCmd1, int writeCmdLength, + u8 *readCmd1, int readCmdLength, + u8 *outBuf, int byteToRead); + +/* chunked version of fts_write */ +int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data, + int dataSize); +/* chunked version of fts_writeRead */ +int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, + int byteToRead, int hasDummyByte); +/* chunked, write followed by another write */ +int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, + AddrSize addrSize2, u64 address, u8 *data, + int dataSize); +/* chunked, write followed by a writeRead */ +int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, + AddrSize addrSize2, u64 address, u8 *outBuf, + int count, int hasDummyByte); +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsSoftware.h b/drivers/input/touchscreen/stm/fts_lib/ftsSoftware.h new file mode 100644 index 000000000000..d00fdc85b3e9 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsSoftware.h @@ -0,0 +1,510 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FW related data * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsSoftware.h + * \brief Contains all the definitions and information related to the IC + * from a fw/driver point of view + */ + + +#ifndef FTS_SOFTWARE_H +#define FTS_SOFTWARE_H +#include <linux/types.h> +#include "ftsHardware.h" + +/* signed type */ +typedef signed char i8; /* /< basic type that represent one signed byte (or 8 + * bits) */ + +/** + * Enumerator which contains all the possible address length expressed in + *bytes. + */ +typedef enum { + NO_ADDR = 0, + BITS_8 = 1, + BITS_16 = 2, + BITS_24 = 3, + BITS_32 = 4, + BITS_40 = 5, + BITS_48 = 6, + BITS_56 = 7, + BITS_64 = 8 +} AddrSize; + + +/******************** NEW API *********************/ + +/* HOST COMMAND */ +/** @defgroup host_command Fw Host op codes + * Valid op codes for fw commands + * @{ + */ + +/** @defgroup scan_mode Scan Mode + * @ingroup host_command + * Set the scanning mode required according to the parameters + * @{ + */ +#define FTS_CMD_SCAN_MODE 0xA0 /* /< OP Code to set scan mode */ +/** @} */ + +/** @defgroup feat_sel Feature Select + * @ingroup host_command + * Set the system defined features to enable/disable according the parameters + * @{ + */ +#define FTS_CMD_FEATURE 0xA2 /* /< OP code to set features */ +/** @} */ + +/** @defgroup sys_cmd System Command + * @ingroup host_command + * Execute a system command to perform core tasks + * @{ + */ +#define FTS_CMD_SYSTEM 0xA4 /* /< OP code to write s system command + * */ +/** @} */ + +/** @} */ /* end host_command group */ + +/* SCAN MODE OPTION (0xA0) */ +/* Scan mode selection */ +/** @defgroup scan_opt Scan Mode Option + * @ingroup scan_mode + * Valid scanning modes and their options + * @{ + */ +#define SCAN_MODE_ACTIVE 0x00 /* /< Select the Active scanning mode */ +#define SCAN_MODE_LOW_POWER 0x01 /* /< Select the low power scanning mode + * */ +#define SCAN_MODE_JIG_1 0x02 /* /< Select the Jig test 1 */ +#define SCAN_MODE_LOCKED 0x03 /* /< Select the Scan mode which will be + * locked */ +/** @}*/ + +/* Active mode option (bitmask) */ +/** @defgroup active_bitmask Active Mode Bitmask + * @ingroup scan_opt + * Bitmask to use to enables the specific scanning with the SCAN_MODE_ACTIVE + * option + * @{ + */ +#define ACTIVE_MULTI_TOUCH 0x01 /* /< Bit 0 MS/SS scan */ +#define ACTIVE_KEY 0x02 /* /< Bit 1 Key scan */ +#define ACTIVE_HOVER 0x04 /* /< Bit 2 Hover scan */ +#define ACTIVE_PROXIMITY 0x08 /* /< Bit 3 Proximity scan */ +#define ACTIVE_FORCE 0x10 /* /< Bit 4 Force scan */ +/** @}*/ + +/* Locked mode option (locked mode) */ +/** @defgroup locked_opt Locked Mode Option + * @ingroup scan_opt + * Options to enable and lock specific scanning with the SCAN_MODE_LOCKED + * option + * @{ + */ +#define LOCKED_ACTIVE 0x00 /* /< Active Scan Mode */ +#define LOCKED_HOVER 0x01 /* /< Hover Scan Mode */ +#define LOCKED_IDLE 0x02 /* /< Idle Scan Mode */ +#define LOCKED_ONLY_SELF 0x03 /* /< Only Self Sense scan mode */ +#define LOCKED_ONLY_MUTUAL_0 0x04 /* /< Only Mutual Sense scan mode at + * lowest freq */ +#define LOCKED_ONLY_MUTUAL_1 0x05 /* /< Only Mutual Sense scan mode */ +#define LOCKED_ONLY_MUTUAL_2 0x06 /* /< Only Mutual Sense scan mode */ +#define LOCKED_ONLY_MUTUAL_3 0x07 /* /< Only Mutual Sense scan mode at + * highest freq */ +#define LOCKED_LP_DETECT 0x10 /* /< Low Power SS */ +#define LOCKED_LP_ACTIVE 0x11 /* /< Low Power MS */ +/** @}*/ + +/* FEATURE SELECT OPTION (0xA2) */ +/* Feature Selection */ +/** @defgroup feat_opt Feature Selection Option + * @ingroup feat_sel + * System defined features that can be enable/disable + * @{ + */ +#define FEAT_SEL_GLOVE 0x00 /* /< Glove Mode */ +#define FEAT_SEL_COVER 0x01 /* /< Cover Mode */ +#define FEAT_SEL_CHARGER 0x02 /* /< Charger Mode */ +#define FEAT_SEL_GESTURE 0x03 /* /< Gesture Mode */ +#define FEAT_SEL_GRIP 0x04 /* /< Grip Detection */ +#define FEAT_SEL_STYLUS 0x07 /* /< Stylus Mode + * (this is a driver define, not + * available in FW) */ +/** @}*/ + +/* Feature Settings */ +#define FEAT_ENABLE 1 /* /< General value to enable a feature + * */ +#define FEAT_DISABLE 0 /* /< General value to disable a feature + * */ + + +/* Charger */ +/** @defgroup charger_opt Charger Mode Option + * @ingroup feat_sel + * Option for Charger Mode, it is a bitmask where the each bit indicate a + * different kind of chager + * @{ + */ +#define CHARGER_CABLE 0x01 /* /< normal usb charger */ +#define CHARGER_WIRLESS 0x02 /* /< wireless charger */ +/** @}*/ + +/* Gestures */ +/** @defgroup gesture_opt Gesture Mode Option + * @ingroup feat_sel + * Gesture IDs of the predefined gesture recognized by the fw. + * The ID represent also the position of the corresponding bit in the gesture + * mask + * @{ + */ +#define GEST_ID_UP_1F 0x01 /* /< Bottom to Top line */ +#define GEST_ID_DOWN_1F 0x02 /* /< Top to bottom line */ +#define GEST_ID_LEFT_1F 0x03 /* /< Right to left line */ +#define GEST_ID_RIGHT_1F 0x04 /* /< Left to right line */ +#define GEST_ID_DBLTAP 0x05 /* /< Double Tap */ +#define GEST_ID_O 0x06 /* /< 'O' */ +#define GEST_ID_C 0x07 /* /< 'C' */ +#define GEST_ID_M 0x08 /* /< 'M' */ +#define GEST_ID_W 0x09 /* /< 'W' */ +#define GEST_ID_E 0x0A /* /< 'e' */ +#define GEST_ID_L 0x0B /* /< 'L' */ +#define GEST_ID_F 0x0C /* /< 'F' */ +#define GEST_ID_V 0x0D /* /< 'V' */ +#define GEST_ID_AT 0x0E /* /< '@' */ +#define GEST_ID_S 0x0F /* /< 'S' */ +#define GEST_ID_Z 0x10 /* /< 'Z' */ +#define GEST_ID_LEFTBRACE 0x11 /* /< '<' */ +#define GEST_ID_RIGHTBRACE 0x12 /* /< '>' */ +#define GEST_ID_CARET 0x13 /* /< '^' */ +/** @}*/ + +/* WRYTE SYSTEM COMMAND (0xA4) */ +/* System command */ +/** @defgroup sys_opt System Command Option + * @ingroup sys_cmd + * Valid System Command Parameters + * @{ + */ +#define SYS_CMD_SPECIAL 0x00 /* /< Special Commands */ +#define SYS_CMD_INT 0x01 /* /< FW Interrupt Control */ +#define SYS_CMD_FORCE_CAL 0x02 /* /< Force Calibration */ +#define SYS_CMD_CX_TUNING 0x03 /* /< CX initialization */ +#define SYS_CMD_ITO 0x04 /* /< ITO test */ +#define SYS_CMD_SAVE_FLASH 0x05 /* /< Saving to flash */ +#define SYS_CMD_LOAD_DATA 0x06 /* /< Load Host data memory */ +#define SYS_CMD_SPECIAL_TUNING 0x08 /* /< Perform some special tuning */ +/** @} */ + +/* System command settings */ +/* Special commands */ +/** @defgroup sys_special_opt Special Command Option + * @ingroup sys_cmd + * Valid special command + * @{ + */ +#define SPECIAL_SYS_RESET 0x00 /* /< System Reset triggered by + * the FW */ +#define SPECIAL_FIFO_FLUSH 0x01 /* /< Flush of the FIFO */ +#define SPECIAL_PANEL_INIT 0x02 /* /< Panel Initialization */ +#define SPECIAL_FULL_PANEL_INIT 0x03 /* /< Full panel initialization + * */ +#define SPECIAL_WRITE_HOST_MEM_TO_FLASH 0x04 /* /< Write */ +/** @} */ + + +/* Force Cal and Cx auto tuning */ +/** @defgroup forcecal_cx_opt Force Cal and Tuning Option + * @ingroup sys_cmd + * Valid bitmask for triggering forcecal or performing manual autotune + * @{ + */ +#define CAL_MS_TOUCH 0x01 /* /< Mutual Sense Touch */ +#define CAL_MS_LOW_POWER 0x02 /* /< Mutual Sense Touch in low power + * mode */ +#define CAL_SS_TOUCH 0x04 /* /< Self Sense Touch */ +#define CAL_SS_IDLE 0x08 /* /< Self Sense Touch in idle mode */ +#define CAL_MS_KEY 0x10 /* /< Mutual Sense Key */ +#define CAL_SS_KEY 0x20 /* /< Self Sense Key */ +#define CAL_MS_FORCE 0x40 /* /< Mutual Sense Force */ +#define CAL_SS_FORCE 0x80 /* /< Self Sense Force */ +/** @} */ + +/* ITO checks (position of the bit in the mask) */ +/** @defgroup ito_opt ITO Test Option + * @ingroup sys_cmd + * Valid option for the ITO test + * @{ + */ +#define ITO_FORCE_OPEN 0x00 /* /< Check if some force channels is + * open */ +#define ITO_SENSE_OPEN 0x01 /* /< Check if some sense channels is + * open */ +#define ITO_FORCE_GROUND 0x02 /* /< Check if some force channels is + * short to ground */ +#define ITO_SENSE_GROUND 0x03 /* /< Check if some sense channels is + * short to ground */ +#define ITO_FORCE_VDD 0x04 /* /< Check if some force channels is + * short to VDD */ +#define ITO_SENSE_VDD 0x05 /* /< Check if some sense channels is + * short to VDD */ +#define ITO_FORCE_FORCE 0x06 /* /< Check force to force channels */ +#define ITO_FORCE_SENSE 0x07 /* /< Check force to sense channels */ +#define ITO_SENSE_SENSE 0x08 /* /< Check sense to sense channels */ +#define ITO_KEY_FORCE_OPEN 0x09 /* /< Check if some force channels used + * for the key is open */ +#define ITO_KEY_SENSE_OPEN 0x0A /* /< Check if some sense channels used + * for the key is open */ +/** @}*/ + +/* Save flash */ +/** @defgroup save_opt Save to Flash Option + * @ingroup sys_cmd + * Valid option for saving data to the Flash + * @{ + */ +#define SAVE_FW_CONF 0x01 /* /< Save the confing to the flash */ +#define SAVE_CX 0x02 /* /< Save the CX to the flash */ +#define SAVE_PANEL_CONF 0x04 /* /< Save the Panel configuration to the flash + * */ +/** @}*/ + +/* Load Data */ +/** @defgroup load_opt Load Host Data Option + * @ingroup sys_cmd + * Valid option to ask to the FW to load host data into the memory + * @{ + */ +#define LOAD_SYS_INFO 0x01 /* /< Load System Info */ +#define LOAD_CX_MS_TOUCH 0x10 /* /< Load MS Init Data for + * Active Mode */ +#define LOAD_CX_MS_LOW_POWER 0x11 /* /< Load MS Init Data for Low + * Power Mode */ +#define LOAD_CX_SS_TOUCH 0x12 /* /< Load SS Init Data for + * Active Mode */ +#define LOAD_CX_SS_TOUCH_IDLE 0x13 /* /< Load SS Init Data for Low + * Power Mode */ +#define LOAD_CX_MS_KEY 0x14 /* /< Load MS Init Data for Key + * */ +#define LOAD_CX_SS_KEY 0x15 /* /< Load SS Init Data for Key + * */ +#define LOAD_CX_MS_FORCE 0x16 /* /< Load MS Init Data for + * Force */ +#define LOAD_CX_SS_FORCE 0x17 /* /< Load SS Init Data for + * Force */ +#define LOAD_SYNC_FRAME_RAW 0x30 /* /< Load a Synchronized Raw + * Frame */ +#define LOAD_SYNC_FRAME_FILTER 0x31 /* /< Load a Synchronized Filter + * Frame */ +#define LOAD_SYNC_FRAME_STRENGTH 0x33 /* /< Load a Synchronized + * Strength Frame */ +#define LOAD_SYNC_FRAME_BASELINE 0x32 /* /< Load a Synchronized + * Baseline Frame */ +#define LOAD_PANEL_CX_TOT_MS_TOUCH 0x50 /* /< Load TOT MS Init Data for + * Active Mode */ +#define LOAD_PANEL_CX_TOT_MS_LOW_POWER 0x51 /* /< Load TOT MS Init Data for + * Low Power Mode */ +#define LOAD_PANEL_CX_TOT_SS_TOUCH 0x52 /* /< Load TOT SS Init Data for + * Active Mode */ +#define LOAD_PANEL_CX_TOT_SS_TOUCH_IDLE 0x53 /* /< Load TOT SS Init Data for + * Low Power Mode */ +#define LOAD_PANEL_CX_TOT_MS_KEY 0x54 /* /< Load TOT MS Init Data for + * Key */ +#define LOAD_PANEL_CX_TOT_SS_KEY 0x55 /* /< Load TOT SS Init Data for + * Key */ +#define LOAD_PANEL_CX_TOT_MS_FORCE 0x56 /* /< Load TOT MS Init Data for + * Force */ +#define LOAD_PANEL_CX_TOT_SS_FORCE 0x57 /* /< Load TOT SS Init Data for + * Force */ +#define LOAD_SENS_CAL_COEFF 0xC0 /* /< Load Sesitivity + * Calibration Coefficients */ +/** @}*/ + +/* Special Tuning */ +/** @defgroup spcl_tun_opt Special Tuning Option + * @ingroup sys_cmd + * Valid special tuning operations which the fw can perform (bitmask) + * @{ + */ +#define SPECIAL_TUNING_LP_TIMER 0x01 /* /< Perform LP Timer calibration */ +#define SPECIAL_TUNING_IOFF 0x02 /* /< Perform Ioff calibration */ + +/** @}*/ + +/* EVENT ID */ +/** @defgroup events_group FW Event IDs and Types + * Event IDs and Types pushed by the FW into the FIFO + * @{ + */ +#define EVT_ID_NOEVENT 0x00 /* /< No Events */ +#define EVT_ID_CONTROLLER_READY 0x03 /* /< Controller ready, issued after a + * system reset. */ +#define EVT_ID_ENTER_POINT 0x13 /* /< Touch enter in the sensing area */ +#define EVT_ID_MOTION_POINT 0x23 /* /< Touch motion (a specific touch + * changed position) */ +#define EVT_ID_LEAVE_POINT 0x33 /* /< Touch leave the sensing area */ +#define EVT_ID_STATUS_UPDATE 0x43 /* /< FW report a system condition + * change */ +#define EVT_ID_USER_REPORT 0x53 /* /< User related events triggered + * (keys, gestures, proximity etc) */ +#define EVT_ID_DEBUG 0xE3 /* /< Debug Info */ +#define EVT_ID_ERROR 0xF3 /* /< Error Event */ + +/* /< Max number of unique event IDs supported */ +#define NUM_EVT_ID (((EVT_ID_ERROR & 0xF0) >> 4) + 1) + +/** @}*/ + +/* STATUS TYPE */ +/** @defgroup status_type Status Event Types + * @ingroup events_group + * Types of EVT_ID_STATUS_UPDATE events + * @{ + */ +#define EVT_TYPE_STATUS_ECHO 0x01 /* /< Echo event, + * contain the first 5 bytes of + * the FW command sent */ +#define EVT_TYPE_STATUS_FRAME_DROP 0x03 /* /< Some frame was skipped + * during the elaboration */ +#define EVT_TYPE_STATUS_FORCE_CAL 0x05 /* /< Force Calibration has + * triggered */ +#define EVT_TYPE_STATUS_WATER 0x06 /* /< Water Mode */ +#define EVT_TYPE_STATUS_SS_RAW_SAT 0x07 /* /< Self Sense data saturated + * */ +/** @} */ + +/* USER TYPE */ +/** @defgroup user_type User Event Types + * @ingroup events_group + * Types of EVT_ID_USER_REPORT events generated by thw FW + * @{ + */ +#define EVT_TYPE_USER_KEY 0x00 /* /< Keys pressed/relesed event report + * */ +#define EVT_TYPE_USER_PROXIMITY 0x01 /* /< Proximity detection event report + * */ +#define EVT_TYPE_USER_GESTURE 0x02 /* /< Gesture detection event report */ +/** @}*/ + +/* ERROR TYPE */ +/** @defgroup error_type Error Event Types + * @ingroup events_group + * Types of EVT_ID_ERROR events reported by the FW + * @{ + */ +#define EVT_TYPE_ERROR_WATCHDOG 0x06 /* /< Watchdog timer expired */ + +#define EVT_TYPE_ERROR_CRC_CFG_HEAD 0x20 /* /< CRC error in the Config + * Area Header */ +#define EVT_TYPE_ERROR_CRC_CFG 0x21 /* /< CRC error in the Config + * Area */ +#define EVT_TYPE_ERROR_CRC_PANEL_HEAD 0x22 /* /< CRC error in the Panel + * Area Header */ +#define EVT_TYPE_ERROR_CRC_PANEL 0x23 /* /< CRC error in the Panel + * Area */ + +#define EVT_TYPE_ERROR_ITO_FORCETOGND 0x60 /* /< Force channel/s short to + * ground */ +#define EVT_TYPE_ERROR_ITO_SENSETOGND 0x61 /* /< Sense channel/s short to + * ground */ +#define EVT_TYPE_ERROR_ITO_FORCETOVDD 0x62 /* /< Force channel/s short to + * VDD */ +#define EVT_TYPE_ERROR_ITO_SENSETOVDD 0x63 /* /< Sense channel/s short to + * VDD */ +#define EVT_TYPE_ERROR_ITO_FORCE_P2P 0x64 /* /< Pin to Pin short Force + * channel/s */ +#define EVT_TYPE_ERROR_ITO_SENSE_P2P 0x65 /* /< Pin to Pin short Sense + * channel/s */ +#define EVT_TYPE_ERROR_ITO_FORCEOPEN 0x66 /* /< Force Panel open */ +#define EVT_TYPE_ERROR_ITO_SENSEOPEN 0x67 /* /< Sense Panel open */ +#define EVT_TYPE_ERROR_ITO_KEYOPEN 0x68 /* /< Key open */ + +#define EVT_TYPE_ERROR_CRC_CX_HEAD 0xA0 /* /< CRC error in the CX Area + * Header */ +#define EVT_TYPE_ERROR_CRC_CX 0xA1 /* /< CRC error in the CX Area + * */ +#define EVT_TYPE_ERROR_FLASH_FAILED 0xA4 /* Flash error, cause unknown */ +#define EVT_TYPE_ERROR_CRC_CX_SUB_HEAD 0xA5 /* /< CRC error in the CX + * Subsection Area Header */ +#define EVT_TYPE_ERROR_CRC_CX_SUB 0xA6 /* /< CRC error in the CX + * Subsection Area */ + +#define EVT_TYPE_ERROR_ESD 0xF0 /* /< ESD error */ +/** @}*/ + + +/** @defgroup address Chip Address + * Collection of HW and SW Addresses useful to collect different kind of data + * @{ + */ + +/** @defgroup config_adr SW Address + * @ingroup address + * Important addresses of data stored into Config memory (and sometimes their + * dimensions) + * @{ + */ +#define ADDR_CONFIG_ID 0x0010 /* /< Starting Address of the config ID + * */ +#define CONFIG_ID_BYTE 2 /* /< Number of bytes of config ID */ +#define ADDR_CONFIG_SENSE_LEN 0x0030 /* /< Address where is stored the number + * of sense channels */ +#define ADDR_CONFIG_FORCE_LEN 0x0031 /* /< Address where is stored the number + * of force channels */ +#define ADDR_CONFIG_AUTOCAL 0x0040 /* /< Address where is stored the Auto + * Calibration register */ +#define ADDR_CONFIG_T_CYCLE 0x00ED /* /< Address where is stored the MS T + * cycle */ +#define ADDR_CONFIG_MNM 0x01F0 /* /< Address where is stored the MNM + * register */ +#define ADDR_CONFIG_MRN 0x01F1 /* /< Address where is stored the MRN + * register */ +#define ADDR_CONFIG_R0_CYCLE 0x01F2 /* /< Address where is stored the first + * R cycle */ +/** @}*/ + +/** @}*/ + +/* ERROR INFO */ +#define ERROR_DUMP_ROW_SIZE 32 /* /< number of rows of the error memory + * */ +#define ERROR_DUMP_COL_SIZE 4 /* /< number of bytes for each row of + * the error memory */ +#define ERROR_DUMP_SIGNATURE 0xFA5005AF /* /< first row signature of a + * proper dump */ + +/* Touch Types */ +#define TOUCH_TYPE_INVALID 0x00 /* /< Invalid touch type */ +#define TOUCH_TYPE_FINGER 0x01 /* /< Finger touch */ +#define TOUCH_TYPE_GLOVE 0x02 /* /< Glove touch */ +#define TOUCH_TYPE_STYLUS 0x03 /* /< Stylus touch */ +#define TOUCH_TYPE_PALM 0x04 /* /< Palm touch */ +#define TOUCH_TYPE_HOVER 0x05 /* /< Hovering touch */ + +/* Keys code */ +#define FTS_KEY_0 0x01 /* /< Key 0 bit */ +#define FTS_KEY_1 0x02 /* /< Key 1 bit */ +#define FTS_KEY_2 0x04 /* /< Key 2 bit */ +#define FTS_KEY_3 0x08 /* /< Key 3 bit */ +#define FTS_KEY_4 0x10 /* /< Key 4 bit */ +#define FTS_KEY_5 0x20 /* /< Key 5 bit */ +#define FTS_KEY_6 0x40 /* /< Key 6 bit */ +#define FTS_KEY_7 0x80 /* /< Key 7 bit */ + +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTest.c b/drivers/input/touchscreen/stm/fts_lib/ftsTest.c new file mode 100644 index 000000000000..f0dedb852bc5 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTest.c @@ -0,0 +1,5268 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS API for MP test * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTest.c + * \brief Contains all the functions related to the Mass Production Test + */ + +#include "ftsCompensation.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsFrame.h" +#include "ftsHardware.h" +#include "ftsIO.h" +#include "ftsSoftware.h" +#include "ftsTest.h" +#include "ftsTime.h" +#include "ftsTool.h" +#include "../fts.h" + + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/serio.h> +#include <linux/time.h> +#include <linux/delay.h> +#include <linux/ctype.h> +#include <linux/firmware.h> + + +#ifdef LIMITS_H_FILE +#include "../fts_limits.h" +#endif + + +TestToDo tests; /* /< global variable that specify the tests to perform during + * the Mass Production Test */ +static LimitFile limit_file; /* /< variable which contains the limit file + * during test */ + +/** + * Initialize the testToDo variable with the default tests to perform during + * the Mass Production Test + * @return OK + */ +int initTestToDo(void) +{ + /*** Initialize Limit File ***/ + limit_file.size = 0; + limit_file.data = NULL; + strlcpy(limit_file.name, " ", MAX_LIMIT_FILE_NAME); + + + tests.MutualRawAdjITO = 1; + + tests.MutualRaw = 1; + tests.MutualRawGap = 0; + tests.MutualRawAdj = 0; + + tests.MutualRawLP = 1; + tests.MutualRawGapLP = 0; + tests.MutualRawAdjLP = 0; + + tests.MutualCx1 = 0; + tests.MutualCx2 = 0; + tests.MutualCx2Adj = 0; + tests.MutualCxTotal = 0; + tests.MutualCxTotalAdj = 0; + +#ifdef PHONE_KEY + tests.MutualKeyRaw = 1; +#else + tests.MutualKeyRaw = 0; +#endif + tests.MutualKeyCx1 = 0; + tests.MutualKeyCx2 = 0; +#ifdef PHONE_KEY + tests.MutualKeyCxTotal = 0; +#else + tests.MutualKeyCxTotal = 0; +#endif + + tests.SelfForceRaw = 1; + tests.SelfForceRawGap = 0; + + tests.SelfForceRawLP = 1; + tests.SelfForceRawGapLP = 0; + + tests.SelfForceIx1 = 0; + tests.SelfForceIx2 = 0; + tests.SelfForceIx2Adj = 0; + tests.SelfForceIxTotal = 0; + tests.SelfForceIxTotalAdj = 0; + tests.SelfForceCx1 = 0; + tests.SelfForceCx2 = 0; + tests.SelfForceCx2Adj = 0; + tests.SelfForceCxTotal = 0; + tests.SelfForceCxTotalAdj = 0; + + tests.SelfSenseRaw = 1; + tests.SelfSenseRawGap = 0; + + tests.SelfSenseRawLP = 1; + tests.SelfSenseRawGapLP = 0; + + tests.SelfSenseIx1 = 0; + tests.SelfSenseIx2 = 0; + tests.SelfSenseIx2Adj = 0; + tests.SelfSenseIxTotal = 0; + tests.SelfSenseIxTotalAdj = 0; + tests.SelfSenseCx1 = 0; + tests.SelfSenseCx2 = 0; + tests.SelfSenseCx2Adj = 0; + tests.SelfSenseCxTotal = 0; + tests.SelfSenseCxTotalAdj = 0; + + return OK; +} + +/** + * Compute the Horizontal adjacent matrix doing the abs of the difference + * between the column i with the i-1 one. \n + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of signed bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjHoriz(i8 *data, int row, int column, u8 **result) +{ + int i, j; + int size = row * (column - 1); + + if (column < 2) { + pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 0; i < row; i++) + for (j = 1; j < column; j++) + *(*result + (i * (column - 1) + (j - 1))) = + abs(data[i * column + j] - data[i * column + + (j - 1)]); + + return OK; +} + +/** + * Compute the Horizontal adjacent matrix of short values doing the abs of + * the difference between the column i with the i-1 one. + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of signed bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which + * will contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjHorizTotal(short *data, int row, int column, u16 **result) +{ + int i, j; + int size = row * (column - 1); + + if (column < 2) { + pr_err("computeAdjHorizTotal: ERROR %08X\n", + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjHorizTotal: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 0; i < row; i++) + for (j = 1; j < column; j++) + *(*result + (i * (column - 1) + (j - 1))) = + abs(data[i * column + j] - data[i * column + + (j - 1)]); + + return OK; +} + +/** + * Compute the Vertical adjacent matrix doing the abs of the difference between + * the row i with the i-1 one. + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other. \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of signed bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjVert(i8 *data, int row, int column, u8 **result) +{ + int i, j; + int size = (row - 1) * (column); + + if (row < 2) { + pr_err("computeAdjVert: ERROR %08X\n", ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjVert: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 1; i < row; i++) + for (j = 0; j < column; j++) + *(*result + ((i - 1) * column + j)) = + abs(data[i * column + j] - data[(i - 1) * + column + j]); + + return OK; +} + +/** + * Compute the Vertical adjacent matrix of short values doing the abs of + * the difference between the row i with the i-1 one. + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other. \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of signed bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjVertTotal(short *data, int row, int column, u16 **result) +{ + int i, j; + int size = (row - 1) * (column); + + if (row < 2) { + pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 1; i < row; i++) + for (j = 0; j < column; j++) + *(*result + ((i - 1) * column + j)) = + abs(data[i * column + j] - data[(i - 1) * + column + j]); + + return OK; +} + +/** + * Compute the Horizontal adjacent matrix doing the abs of the difference + * between the column i with the i-1 one. \n + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of unsigned bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjHorizFromU(u8 *data, int row, int column, u8 **result) +{ + int i, j; + int size = row * (column - 1); + + if (column < 2) { + pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 0; i < row; i++) + for (j = 1; j < column; j++) + *(*result + (i * (column - 1) + (j - 1))) = + abs(data[i * column + j] - data[i * column + + (j - 1)]); + + return OK; +} + +/** + * Compute the Horizontal adjacent matrix of u16 values doing the abs of + * the difference between the column i with the i-1 one. + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of unsigned bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjHorizTotalFromU(u16 *data, int row, int column, u16 **result) +{ + int i, j; + int size = row * (column - 1); + + if (column < 2) { + pr_err("computeAdjHorizTotal: ERROR %08X\n", + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjHorizTotal: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 0; i < row; i++) + for (j = 1; j < column; j++) + *(*result + (i * (column - 1) + (j - 1))) = + abs(data[i * column + j] - data[i * column + + (j - 1)]); + + return OK; +} + +/** + * Compute the Vertical adjacent matrix doing the abs of the difference between + * the row i with the i-1 one. + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other. \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of unsigned bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjVertFromU(u8 *data, int row, int column, u8 **result) +{ + int i, j; + int size = (row - 1) * (column); + + if (row < 2) { + pr_err("computeAdjVert: ERROR %08X\n", ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjVert: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 1; i < row; i++) + for (j = 0; j < column; j++) + *(*result + ((i - 1) * column + j)) = + abs(data[i * column + j] - data[(i - 1) * + column + j]); + + return OK; +} + +/** + * Compute the Vertical adjacent matrix of u16 values doing the abs of + * the difference between the row i with the i-1 one. + * Both the original data matrix and the adj matrix are disposed as 1 dimension + * array one row after the other. \n + * The resulting matrix has one column less than the starting original one \n + * @param data pointer to the array of unsigned bytes containing the original + * data + * @param row number of rows of the original data + * @param column number of columns of the original data + * @param result pointer of a pointer to an array of unsigned bytes which will + * contain the adj matrix + * @return OK if success or an error code which specify the type of error + */ +int computeAdjVertTotalFromU(u16 *data, int row, int column, u16 **result) +{ + int i, j; + int size = (row - 1) * (column); + + if (row < 2) { + pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL); + if (*result == NULL) { + pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_ALLOC); + return ERROR_ALLOC; + } + + for (i = 1; i < row; i++) + for (j = 0; j < column; j++) + *(*result + ((i - 1) * column + j)) = + abs(data[i * column + j] - data[(i - 1) * + column + j]); + + return OK; +} + + + +/** + * Check that each value of a matrix of short doesn't exceed a min and a Max + * value + * (these values are included in the interval). \n + * The matrix is stored as 1 dimension array one row after the other. \n + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param min minimum value allowed + * @param max Maximum value allowed + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMinMax(short *data, int row, int column, int min, int max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] < min || data[i * column + j] > + max) { + pr_err("checkLimitsMinMax: Node[%d,%d] = %d exceed limit [%d, %d]\n", + i, j, data[i * column + j], min, max); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Check that the difference between the max and min of a matrix of short + * is less or equal to a threshold.\n + * The matrix is stored as 1 dimension array one row after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param threshold threshold value allowed + * @return OK if the difference is <= to threshold otherwise + * ERROR_TEST_CHECK_FAIL + */ +int checkLimitsGap(short *data, int row, int column, int threshold) +{ + int i, j; + int min_node; + int max_node; + + if (row == 0 || column == 0) { + pr_err("checkLimitsGap: invalid number of rows = %d or columns = %d ERROR %08X\n", + row, column, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + min_node = data[0]; + max_node = data[0]; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] < min_node) + min_node = data[i * column + j]; + else if (data[i * column + j] > max_node) + max_node = data[i * column + j]; + } + } + + if (max_node - min_node > threshold) { + pr_err("checkLimitsGap: GAP = %d exceed limit %d\n", + max_node - min_node, threshold); + return ERROR_TEST_CHECK_FAIL; + } else + return OK; +} + +/** + * Check that each value of a matrix of i8 doesn't exceed a specific min and + * Max value set for each node (these values are included in the interval). \n + * The matrixes of data, min and max values are stored as 1 dimension arrays + * one row after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param min pointer to a matrix which specify the minimum value allowed for + * each node + * @param max pointer to a matrix which specify the Maximum value allowed for + * each node + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMap(i8 *data, int row, int column, int *min, int *max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] < min[i * column + j] || + data[i * column + j] > max[i * column + j]) { + pr_err("checkLimitsMap: Node[%d,%d] = %d exceed limit [%d, %d]\n", + i, j, data[i * column + j], + min[i * column + j], + max[i * column + j]); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Check that each value of a matrix of short doesn't exceed a specific min and + * Max value set for each node (these values are included in the interval). + * The matrixes of data, min and max values are stored as 1 dimension arrays + * one row after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param min pointer to a matrix which specify the minimum value allowed for + * each node + * @param max pointer to a matrix which specify the Maximum value allowed for + * each node + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMapTotal(short *data, int row, int column, int *min, int *max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] < min[i * column + j] || + data[i * column + j] > max[i * column + j]) { + pr_err("checkLimitsMapTotal: Node[%d,%d] = %d exceed limit [%d, %d]\n", + i, j, data[i * column + j], + min[i * column + j], + max[i * column + j]); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Check that each value of a matrix of u8 doesn't exceed a specific min and + * Max value set for each node (these values are included in the interval). \n + * The matrixes of data, min and max values are stored as 1 dimension arrays + * one row after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param min pointer to a matrix which specify the minimum value allowed for + * each node + * @param max pointer to a matrix which specify the Maximum value allowed for + * each node + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMapFromU(u8 *data, int row, int column, int *min, int *max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] < min[i * column + j] || + data[i * column + j] > max[i * column + j]) { + pr_err("checkLimitsMap: Node[%d,%d] = %d exceed limit [%d, %d]\n", + i, j, data[i * column + j], + min[i * column + j], + max[i * column + j]); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Check that each value of a matrix of u16 doesn't exceed a specific min and + * Max value set for each node (these values are included in the interval). + * The matrixes of data, min and max values are stored as 1 dimension arrays + * one row after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param min pointer to a matrix which specify the minimum value allowed for + * each node + * @param max pointer to a matrix which specify the Maximum value allowed for + * each node + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMapTotalFromU(u16 *data, int row, int column, int *min, int *max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] < min[i * column + j] || + data[i * column + j] > max[i * column + j]) { + pr_err("checkLimitsMapTotal: Node[%d,%d] = %d exceed limit [%d, %d]\n", + i, j, data[i * column + j], + min[i * column + j], + max[i * column + j]); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Check that each value of a matrix of u8 doesn't exceed a specific Max value + * set for each node (max value is included in the interval). + * The matrixes of data and max values are stored as 1 dimension arrays one row + * after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param max pointer to a matrix which specify the Maximum value allowed for + * each node + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMapAdj(u8 *data, int row, int column, int *max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] > max[i * column + j]) { + pr_err("checkLimitsMapAdj: Node[%d,%d] = %d exceed limit > %d\n", + i, j, + data[i * column + j], + max[i * column + j]); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Check that each value of a matrix of u16 doesn't exceed a specific Max value + * set for each node (max value is included in the interval). + * The matrixes of data and max values are stored as 1 dimension arrays one row + * after the other. + * @param data pointer to the array of short containing the data to check + * @param row number of rows of data + * @param column number of columns of data + * @param max pointer to a matrix which specify the Maximum value allowed for + * each node + * @return the number of elements that overcome the specified interval (0 = OK) + */ +int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max) +{ + int i, j; + int count = 0; + + for (i = 0; i < row; i++) { + for (j = 0; j < column; j++) { + if (data[i * column + j] > max[i * column + j]) { + pr_err("checkLimitsMapAdjTotal: Node[%d,%d] = %d exceed limit > %d\n", + i, j, + data[i * column + j], + max[i * column + j]); + count++; + } + } + } + + return count; /* if count is 0 = OK, test completed successfully */ +} + +/** + * Perform an ITO test setting all the possible options + * (see @link ito_opt ITO Options @endlink) and checking MS Raw ADJ if enabled + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ito(char *path_limits, TestToDo *todo) +{ + int res = OK; + u8 sett[2] = { 0x00, 0x00 }; + MutualSenseFrame msRawFrame; + int *thresholds = NULL; + u16 *adj = NULL; + int trows, tcolumns; + + pr_info("ITO Production test is starting...\n"); + + res = fts_system_reset(); + if (res < 0) { + pr_err("%s: ERROR %08X\n", __func__, ERROR_PROD_TEST_ITO); + return res | ERROR_PROD_TEST_ITO; + } + + sett[0] = SPECIAL_TUNING_IOFF; + pr_info("Trimming Ioff...\n"); + res = writeSysCmd(SYS_CMD_SPECIAL_TUNING, sett, 2); + if (res < OK) { + pr_err("production_test_ito: Trimm Ioff ERROR %08X\n", + (res | ERROR_PROD_TEST_ITO)); + return res | ERROR_PROD_TEST_ITO; + } + + sett[0] = 0xFF; + sett[1] = 0xFF; + pr_info("ITO Check command sent...\n"); + res = writeSysCmd(SYS_CMD_ITO, sett, 2); + if (res < OK) { + pr_err("production_test_ito: ERROR %08X\n", + (res | ERROR_PROD_TEST_ITO)); + return res | ERROR_PROD_TEST_ITO; + } + + pr_info("ITO Command = OK!\n"); + + pr_info("MS RAW ITO ADJ TEST:\n"); + if (todo->MutualRawAdjITO == 1) { + pr_info("Collecting MS Raw data...\n"); + res |= getMSFrame3(MS_RAW, &msRawFrame); + if (res < OK) { + pr_err("%s: getMSFrame failed... ERROR %08X\n", + __func__, ERROR_PROD_TEST_ITO); + goto ERROR; + } + + print_frame_short("MS Raw ITO frame =", + array1dTo2d_short( + msRawFrame.node_data, + msRawFrame.node_data_size, + msRawFrame.header.sense_node), + msRawFrame.header.force_node, + msRawFrame.header.sense_node); + + pr_info("MS RAW ITO ADJ HORIZONTAL TEST:\n"); + res = computeAdjHorizTotal(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + &adj); + if (res < OK) { + pr_err("%s: computeAdjHoriz failed... ERROR %08X\n", + __func__, ERROR_PROD_TEST_ITO); + goto ERROR; + } + + res = parseProductionTestLimits(path_limits, &limit_file, + MS_RAW_ITO_ADJH, &thresholds, + &trows, &tcolumns); + if (res < OK || (trows != msRawFrame.header.force_node || + tcolumns != msRawFrame.header.sense_node - + 1)) { + pr_err("%s: parseProductionTestLimits MS_RAW_ITO_ADJH failed... ERROR %08X\n", + __func__, ERROR_PROD_TEST_DATA); + goto ERROR; + } + + + res = checkLimitsMapAdjTotal(adj, msRawFrame.header.force_node, + msRawFrame.header.sense_node - 1, + thresholds); + if (res != OK) { + pr_err("production_test_data: checkLimitsAdj MS RAW ITO ADJH failed... ERROR COUNT = %d\n", + res); + pr_err("MS RAW ITO ADJ HORIZONTAL TEST:.................FAIL\n\n"); + res = ERROR_PROD_TEST_ITO; + goto ERROR; + } else + pr_info("MS RAW ITO ADJ HORIZONTAL TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + + kfree(adj); + adj = NULL; + + pr_info("MS RAW ITO ADJ VERTICAL TEST:\n"); + res = computeAdjVertTotal(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + &adj); + if (res < OK) { + pr_err("%s: computeAdjVert failed... ERROR %08X\n", + __func__, ERROR_PROD_TEST_ITO); + goto ERROR; + } + + res = parseProductionTestLimits(path_limits, &limit_file, + MS_RAW_ITO_ADJV, &thresholds, + &trows, &tcolumns); + if (res < OK || (trows != msRawFrame.header.force_node - 1 || + tcolumns != msRawFrame.header.sense_node)) { + pr_err("%s: parseProductionTestLimits MS_RAW_ITO_ADJV failed... ERROR %08X\n", + __func__, ERROR_PROD_TEST_ITO); + goto ERROR; + } + + + res = checkLimitsMapAdjTotal(adj, msRawFrame.header.force_node - + 1, msRawFrame.header.sense_node, + thresholds); + if (res != OK) { + pr_err("%s: checkLimitsAdj MS RAW ITO ADJV failed... ERROR COUNT = %d\n", + __func__, res); + pr_err("MS RAW ITO ADJ VERTICAL TEST:.................FAIL\n\n"); + res = ERROR_PROD_TEST_ITO; + goto ERROR; + } else + pr_info("MS RAW ITO ADJ VERTICAL TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + + kfree(adj); + adj = NULL; + } else + pr_info("MS RAW ITO ADJ TEST:.................SKIPPED\n"); + +ERROR: + if (thresholds != NULL) + kfree(thresholds); + if (adj != NULL) + kfree(adj); + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + freeLimitsFile(&limit_file); + res |= fts_system_reset(); + if (res < OK) { + pr_err("production_test_ito: ERROR %08X\n", + ERROR_PROD_TEST_ITO); + res = (res | ERROR_PROD_TEST_ITO); + } + return res; +} + +/** + * Perform the Initialization of the IC + * @param type type of initialization to do + * (see @link sys_special_opt Initialization Options (Full or Panel) @endlink) + * @return OK if success or an error code which specify the type of error + */ +int production_test_initialization(u8 type) +{ + int res; + + pr_info("INITIALIZATION Production test is starting...\n"); + if (type != SPECIAL_PANEL_INIT && type != SPECIAL_FULL_PANEL_INIT) { + pr_err("production_test_initialization: Type incompatible! Type = %02X ERROR %08X\n", + type, ERROR_OP_NOT_ALLOW | + ERROR_PROD_TEST_INITIALIZATION); + return ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_INITIALIZATION; + } + + res = fts_system_reset(); + if (res < 0) { + pr_err("production_test_initialization: ERROR %08X\n", + ERROR_PROD_TEST_INITIALIZATION); + return res | ERROR_PROD_TEST_INITIALIZATION; + } + + pr_info("INITIALIZATION command sent... %02X\n", type); + res = writeSysCmd(SYS_CMD_SPECIAL, &type, 1); + if (res < OK) { + pr_err("production_test_initialization: ERROR %08X\n", + (res | ERROR_PROD_TEST_INITIALIZATION)); + return res | ERROR_PROD_TEST_INITIALIZATION; + } + + + pr_info("Refresh Sys Info...\n"); + res |= readSysInfo(1); /* need to update the chipInfo in order + * to refresh several versions */ + + if (res < 0) { + pr_err("production_test_initialization: read sys info ERROR %08X\n", + ERROR_PROD_TEST_INITIALIZATION); + res = (res | ERROR_PROD_TEST_INITIALIZATION); + } + + return res; +} + + +// @param signature value of the MP flag to save if the Mass Production Test succeed +/** + * Perform a FULL (ITO + INIT + DATA CHECK) Mass Production Test of the IC + * @param pathThresholds name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param saveInit if >0 (possible values: NO_INIT, SPECIAL_PANEL_INIT or + * SPECIAL_FULL_PANEL_INIT), + * the Initialization of the IC is executed otherwise it is skipped + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_main(char *pathThresholds, int stop_on_fail, int saveInit, + TestToDo *todo) +{ + int res, ret; + + pr_info("MAIN Production test is starting...\n"); + + pr_info("ITO TEST:\n"); + res = production_test_ito(pathThresholds, todo); + if (res < 0) { + pr_err("Error during ITO TEST! ERROR %08X\n", res); + goto END;/* in case of ITO TEST failure is no sense keep going + * */ + } else + pr_info("ITO TEST OK!\n"); + + pr_info("INITIALIZATION TEST :\n"); + if (saveInit != NO_INIT) { + res = production_test_initialization((u8)saveInit); + if (res < 0) { + pr_err("Error during INITIALIZATION TEST! ERROR %08X\n", + res); + if (stop_on_fail) + goto END; + } else + pr_info("INITIALIZATION TEST OK!\n"); + } else + pr_info("INITIALIZATION TEST :................. SKIPPED\n"); + + if (saveInit == 1) { + pr_info("Cleaning up...\n"); + ret = fts_system_reset(); + if (ret < 0) { + pr_err("production_test_main: system reset ERROR %08X\n", + ret); + res |= ret; + if (stop_on_fail) + goto END; + } + } + + pr_info("PRODUCTION DATA TEST:\n"); + ret = production_test_data(pathThresholds, stop_on_fail, todo); + if (ret < 0) + pr_err("Error during PRODUCTION DATA TEST! ERROR %08X\n", ret); + else + pr_info("PRODUCTION DATA TEST OK!\n"); + + res |= ret; + /* the OR is important because if the data test is OK but + * the init test fail, the main production test result should = FAIL */ + +END: + if (res < 0) { + pr_err("MAIN Production test finished.................FAILED\n"); + return res; + } else { + pr_info("MAIN Production test finished.................OK\n"); + return OK; + } +} + +/** + * Perform all the test selected in a TestTodo variable related to MS raw data + * (touch, keys etc..) + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo) +{ + int ret, count_fail = 0; + MutualSenseFrame msRawFrame; + + + int *thresholds = NULL; + int trows, tcolumns; + + u16 *adj = NULL; + + /************** Mutual Sense Test *************/ + pr_info("MS RAW DATA TEST is starting...\n"); + if (todo->MutualRaw == 1 || todo->MutualRawGap == 1 || + todo->MutualRawAdj == 1) { + ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_ACTIVE); + mdelay(WAIT_FOR_FRESH_FRAMES); + ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + ret |= getMSFrame3(MS_RAW, &msRawFrame); + if (ret < OK) { + pr_err("production_test_data: getMSFrame failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + print_frame_short("MS Raw frame =", + array1dTo2d_short( + msRawFrame.node_data, + msRawFrame.node_data_size, + msRawFrame.header.sense_node), + msRawFrame.header.force_node, + msRawFrame.header.sense_node); + + pr_info("MS RAW MIN MAX TEST:\n"); + if (todo->MutualRaw == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_MIN_MAX, + &thresholds, &trows, + &tcolumns); + if (ret < OK || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + + ret = checkLimitsMinMax(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + thresholds[0], + thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax MS RAW failed... ERROR COUNT = %d\n", + ret); + pr_err("MS RAW MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW MIN MAX TEST:.................OK\n"); + kfree(thresholds); + thresholds = NULL; + } else + pr_info("MS RAW MIN MAX TEST:.................SKIPPED\n"); + + pr_info("MS RAW GAP TEST:\n"); + if (todo->MutualRawGap == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, MS_RAW_GAP, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_GAP failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsGap(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + thresholds[0]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsGap MS RAW failed... ERROR = %08X\n", + ret); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW GAP TEST:.................OK\n\n"); + kfree(thresholds); + thresholds = NULL; + } else + pr_info("MS RAW GAP TEST:.................SKIPPED\n"); + + pr_info("MS RAW ADJ TEST:\n"); + if (todo->MutualRawAdj == 1) { + pr_info("MS RAW ADJ HORIZONTAL TEST:\n"); + ret = computeAdjHorizTotal(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + &adj); + if (ret < OK) { + pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_ADJH, + &thresholds, &trows, + &tcolumns); + if (ret < OK || (trows != + msRawFrame.header.force_node || + tcolumns != + msRawFrame.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_ADJH failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + + ret = checkLimitsMapAdjTotal(adj, + msRawFrame.header. + force_node, + msRawFrame.header. + sense_node - 1, + thresholds); + if (ret != OK) { + pr_err("production_test_data: checkLimitsAdj MS RAW ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("MS RAW ADJ HORIZONTAL TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW ADJ HORIZONTAL TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + + kfree(adj); + adj = NULL; + + pr_info("MS RAW ADJ VERTICAL TEST:\n"); + ret = computeAdjVertTotal(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + &adj); + if (ret < OK) { + pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_ADJV, + &thresholds, &trows, + &tcolumns); + if (ret < OK || (trows != msRawFrame.header.force_node - + 1 || tcolumns != + msRawFrame.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_ADJV failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + + ret = checkLimitsMapAdjTotal(adj, + msRawFrame.header. + force_node - 1, + msRawFrame.header. + sense_node, thresholds); + if (ret != OK) { + pr_err("production_test_data: checkLimitsAdj MS RAW ADJV failed... ERROR COUNT = %d\n", + ret); + pr_err("MS RAW ADJ VERTICAL TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW ADJ VERTICAL TEST:.................OK\n"); + kfree(thresholds); + thresholds = NULL; + + kfree(adj); + adj = NULL; + } else + pr_info("MS RAW ADJ TEST:.................SKIPPED\n"); + } else + pr_info("MS RAW FRAME TEST:.................SKIPPED\n"); + + pr_info("MS KEY RAW TEST:\n"); + if (todo->MutualKeyRaw == 1) { + ret = production_test_ms_key_raw(path_limits); + if (ret < 0) { + pr_err("production_test_data: production_test_ms_key_raw failed... ERROR = %08X\n", + ret); + count_fail += 1; + if (count_fail == 1) { + pr_err("MS RAW DATA TEST:.................FAIL fails_count = %d\n\n", + count_fail); + goto ERROR_LIMITS; + } + } + } else + pr_info("MS KEY RAW TEST:.................SKIPPED\n"); + + ret = production_test_ms_raw_lp(path_limits, stop_on_fail, todo); + if (ret < 0) { + pr_err("production_test_data: production_test_ms_raw_lp failed... ERROR = %08X\n", + ret); + count_fail += 1; + if (count_fail == 1) { + pr_err("MS RAW DATA TEST:.................FAIL fails_count = %d\n\n", + count_fail); + goto ERROR_LIMITS; + } + } + +ERROR: + + if (count_fail == 0) { + if (msRawFrame.node_data != NULL) { + kfree(msRawFrame.node_data); + msRawFrame.node_data = NULL; + } + pr_info("MS RAW DATA TEST finished!.................OK\n"); + return OK; + } else { + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + if (thresholds != NULL) + kfree(thresholds); + if (adj != NULL) + kfree(adj); + pr_err("MS RAW DATA TEST:.................FAIL fails_count = %d\n\n", + count_fail); + return ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL; + } + + +ERROR_LIMITS: + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + if (thresholds != NULL) + kfree(thresholds); + return ret; +} + + +/** + * Perform all the test selected in a TestTodo variable related to MS low power + * raw data + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ms_raw_lp(char *path_limits, int stop_on_fail, + TestToDo *todo) +{ + int ret, count_fail = 0; + MutualSenseFrame msRawFrame; + + + int *thresholds = NULL; + int trows, tcolumns; + + u16 *adj = NULL; + + /************** Mutual Sense Test **************/ + pr_info("MS RAW LP DATA TEST:\n"); + if (todo->MutualRawLP == 1 || todo->MutualRawGapLP == 1 || + todo->MutualRawAdjLP == 1) { + ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_LP_ACTIVE); + mdelay(WAIT_FOR_FRESH_FRAMES); + ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + ret |= getMSFrame3(MS_RAW, &msRawFrame); + if (ret < 0) { + pr_err("production_test_data: getMSFrame failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + print_frame_short("MS Raw LP frame =", + array1dTo2d_short( + msRawFrame.node_data, + msRawFrame.node_data_size, + msRawFrame.header.sense_node), + msRawFrame.header.force_node, + msRawFrame.header.sense_node); + + pr_info("MS RAW LP MIN MAX TEST:\n"); + if (todo->MutualRawLP == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_LP_MIN_MAX, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_LP_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + + ret = checkLimitsMinMax(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + thresholds[0], + thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax MS RAW LP failed... ERROR COUNT = %d\n", + ret); + pr_err("MS RAW LP MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW LP MIN MAX TEST:.................OK\n"); + kfree(thresholds); + thresholds = NULL; + } else + pr_info("MS RAW LP MIN MAX TEST:.................SKIPPED\n"); + + pr_info("MS RAW LP GAP TEST:\n"); + if (todo->MutualRawGapLP == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_LP_GAP, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_LP_GAP failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsGap(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + thresholds[0]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsGap MS RAW LP failed... ERROR = %08X\n", + ret); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW LP GAP TEST:.................OK\n\n"); + kfree(thresholds); + thresholds = NULL; + } else + pr_info("MS RAW LP GAP TEST:.................SKIPPED\n"); + + pr_info("MS RAW LP ADJ TEST:\n"); + if (todo->MutualRawAdjLP == 1) { + pr_info("MS RAW LP ADJ HORIZONTAL TEST:\n"); + ret = computeAdjHorizTotal(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + &adj); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_LP_ADJH, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != msRawFrame.header.force_node || + tcolumns != + msRawFrame.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_LP_ADJH failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + + ret = checkLimitsMapAdjTotal(adj, + msRawFrame.header. + force_node, + msRawFrame.header. + sense_node - 1, + thresholds); + if (ret != OK) { + pr_err("production_test_data: checkLimitsAdj MS RAW LP ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("MS RAW LP ADJ HORIZONTAL TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW LP ADJ HORIZONTAL TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + + kfree(adj); + adj = NULL; + + pr_info("MS RAW LP ADJ VERTICAL TEST:\n"); + ret = computeAdjVertTotal(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + &adj); + if (ret < 0) { + pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_RAW_LP_ADJV, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != msRawFrame.header.force_node - + 1 || tcolumns != + msRawFrame.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_RAW_ADJV failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + + ret = checkLimitsMapAdjTotal(adj, + msRawFrame.header. + force_node - 1, + msRawFrame.header. + sense_node, thresholds); + if (ret != OK) { + pr_err("production_test_data: checkLimitsAdj MS RAW ADJV failed... ERROR COUNT = %d\n", + ret); + pr_err("MS RAW LP ADJ VERTICAL TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail == 1) + goto ERROR; + } else + pr_info("MS RAW LP ADJ VERTICAL TEST:.................OK\n"); + kfree(thresholds); + thresholds = NULL; + + kfree(adj); + adj = NULL; + } else + pr_info("MS RAW LP ADJ TEST:.................SKIPPED\n"); + } else + pr_info("MS RAW LP FRAME TEST:.................SKIPPED\n"); + +ERROR: + if (count_fail == 0) { + if (msRawFrame.node_data != NULL) { + kfree(msRawFrame.node_data); + msRawFrame.node_data = NULL; + } + pr_info("MS RAW DATA TEST finished!.................OK\n"); + return OK; + } else { + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + if (thresholds != NULL) + kfree(thresholds); + if (adj != NULL) + kfree(adj); + pr_err("MS RAW LP DATA TEST:.................FAIL fails_count = %d\n\n", + count_fail); + return ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL; + } + + +ERROR_LIMITS: + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + if (thresholds != NULL) + kfree(thresholds); + return ret; +} + +/** + * Perform MS raw test for keys data + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @return OK if success or an error code which specify the type of error + */ +int production_test_ms_key_raw(char *path_limits) +{ + int ret; + MutualSenseFrame msRawFrame; + + int *thresholds = NULL; + int trows, tcolumns; + + /************** Mutual Sense Test **************/ + pr_info("MS KEY RAW DATA TEST is starting...\n"); + ret = setScanMode(SCAN_MODE_ACTIVE, 0xFF); + mdelay(WAIT_FOR_FRESH_FRAMES); + ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + ret |= getMSFrame3(MS_KEY_RAW, &msRawFrame); + if (ret < 0) { + pr_err("production_test_data: getMSKeyFrame failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_KEY_RAW_MIN_MAX, &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits MS_KEY_RAW_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMinMax(msRawFrame.node_data, + msRawFrame.header.force_node, + msRawFrame.header.sense_node, + thresholds[0], thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax MS KEY RAW failed... ERROR COUNT = %d\n", + ret); + goto ERROR; + } else + pr_info("MS KEY RAW TEST:.................OK\n\n"); + + kfree(thresholds); + thresholds = NULL; + + kfree(msRawFrame.node_data); + msRawFrame.node_data = NULL; + return OK; + +ERROR: + print_frame_short("MS Key Raw frame =", array1dTo2d_short( + msRawFrame.node_data, + msRawFrame.node_data_size, + msRawFrame.header.sense_node), + msRawFrame.header.force_node, + msRawFrame.header.sense_node); + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + if (thresholds != NULL) + kfree(thresholds); + pr_err("MS KEY RAW TEST:.................FAIL\n\n"); + return ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL; + +ERROR_LIMITS: + if (msRawFrame.node_data != NULL) + kfree(msRawFrame.node_data); + if (thresholds != NULL) + kfree(thresholds); + return ret; +} + +/** + * Perform all the tests selected in a TestTodo variable related to MS Init + * data (touch, keys etc..) + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo) +{ + int ret; + int count_fail = 0; + + int *thresholds = NULL; + int *thresholds_min = NULL; + int *thresholds_max = NULL; + int trows, tcolumns; + + MutualSenseData msCompData; + TotMutualSenseData totCompData; + + u8 *adjhor = NULL; + + u8 *adjvert = NULL; + + u16 container; + /* u16 *total_cx = NULL; */ + u16 *total_adjhor = NULL; + u16 *total_adjvert = NULL; + + + /* MS CX TEST */ + pr_info("MS CX Testes are starting...\n"); + + ret = readMutualSenseCompensationData(LOAD_CX_MS_TOUCH, &msCompData); + /* read MS compensation data */ + if (ret < 0) { + pr_err("production_test_data: readMutualSenseCompensationData failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + ret = readTotMutualSenseCompensationData(LOAD_PANEL_CX_TOT_MS_TOUCH, + &totCompData); + /* read TOT MS compensation data */ + if (ret < 0) { + pr_err("production_test_data: readTotMutualSenseCompensationData failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + kfree(msCompData.node_data); + msCompData.node_data = NULL; + return ret | ERROR_PROD_TEST_DATA; + } + + pr_info("MS CX1 TEST:\n"); + if (todo->MutualCx1 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_CX1_MIN_MAX, &thresholds, + &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits MS_CX1_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + container = (u16)msCompData.cx1; + ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], + thresholds[1]); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax MS CX1 failed... ERROR COUNT = %d\n", + ret); + pr_err("MS CX1 TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS CX1 TEST:.................OK\n\n"); + } else + pr_info("MS CX1 TEST:.................SKIPPED\n\n"); + + kfree(thresholds); + thresholds = NULL; + + pr_info("MS CX2 MIN MAX TEST:\n"); + if (todo->MutualCx2 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_CX2_MAP_MIN, &thresholds_min, + &trows, &tcolumns); + /* load min thresholds */ + if (ret < 0 || (trows != msCompData.header.force_node || + tcolumns != msCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_CX2_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_CX2_MAP_MAX, &thresholds_max, + &trows, &tcolumns); + /* load max thresholds */ + if (ret < 0 || (trows != msCompData.header.force_node || + tcolumns != msCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_CX2_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMap(msCompData.node_data, + msCompData.header.force_node, + msCompData.header.sense_node, + thresholds_min, thresholds_max); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap MS CX2 MIN MAX failed... ERROR COUNT = %d\n", + ret); + pr_err("MS CX2 MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS CX2 MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("MS CX2 MIN MAX TEST:.................SKIPPED\n\n"); + + pr_info("MS CX2 ADJ TEST:\n"); + if (todo->MutualCx2Adj == 1) { + /* MS CX2 ADJ HORIZ */ + pr_info("MS CX2 ADJ HORIZ TEST:\n"); + + ret = computeAdjHoriz(msCompData.node_data, + msCompData.header.force_node, + msCompData.header.sense_node, + &adjhor); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("MS CX2 ADJ HORIZ computed!\n"); + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_CX2_ADJH_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + if (ret < 0 || (trows != msCompData.header.force_node || + tcolumns != msCompData.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits MS_CX2_ADJH_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdj(adjhor, msCompData.header.force_node, + msCompData.header.sense_node - 1, + thresholds_max); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj CX2 ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("MS CX2 ADJ HORIZ TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS CX2 ADJ HORIZ TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(adjhor); + adjhor = NULL; + + /* MS CX2 ADJ VERT */ + pr_info("MS CX2 ADJ VERT TEST:\n"); + + ret = computeAdjVert(msCompData.node_data, + msCompData.header.force_node, + msCompData.header.sense_node, + &adjvert); + if (ret < 0) { + pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("MS CX2 ADJ VERT computed!\n"); + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_CX2_ADJV_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + if (ret < 0 || (trows != msCompData.header.force_node - 1 || + tcolumns != msCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_CX2_ADJV_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdj(adjvert, msCompData.header.force_node - + 1, msCompData.header.sense_node - 1, + thresholds_max); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj CX2 ADJV failed... ERROR COUNT = %d\n", + ret); + pr_err("MS CX2 ADJ HORIZ TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS CX2 ADJ VERT TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(adjvert); + adjvert = NULL; + } else + pr_info("MS CX2 ADJ TEST:.................SKIPPED\n\n"); + + /* START OF TOTAL CHECK */ + pr_info("MS TOTAL CX TEST:\n"); + + if (todo->MutualCxTotal == 1 || todo->MutualCxTotalAdj == 1) { + pr_info("MS TOTAL CX MIN MAX TEST:\n"); + if (todo->MutualCxTotal == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_TOTAL_CX_MAP_MIN, + &thresholds_min, + &trows, &tcolumns); + /* load min thresholds */ + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_TOTAL_CX_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + /* load max thresholds */ + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapTotal(totCompData.node_data, + totCompData.header.force_node, + totCompData.header.sense_node, + thresholds_min, + thresholds_max); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap MS TOTAL CX TEST failed... ERROR COUNT = %d\n", + ret); + pr_err("MS TOTAL CX MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS TOTAL CX MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("MS TOTAL CX MIN MAX TEST:.................SKIPPED\n\n"); + + + pr_info("MS TOTAL CX ADJ TEST:\n"); + if (todo->MutualCxTotalAdj == 1) { + /* MS TOTAL CX ADJ HORIZ */ + pr_info("MS TOTAL CX ADJ HORIZ TEST:\n"); + + ret = computeAdjHorizTotal(totCompData.node_data, + totCompData.header.force_node, + totCompData.header.sense_node, + &total_adjhor); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("MS TOTAL CX ADJ HORIZ computed!\n"); + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_TOTAL_CX_ADJH_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != + totCompData.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_ADJH_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdjTotal(total_adjhor, + totCompData.header. + force_node, + totCompData.header. + sense_node - 1, + thresholds_max); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj MS TOTAL CX ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("MS TOTAL CX ADJ HORIZ TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS TOTAL CX ADJ HORIZ TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(total_adjhor); + total_adjhor = NULL; + + /* MS TOTAL CX ADJ VERT */ + pr_info("MS TOTAL CX ADJ VERT TEST:\n"); + + ret = computeAdjVertTotal(totCompData.node_data, + totCompData.header.force_node, + totCompData.header.sense_node, + &total_adjvert); + if (ret < 0) { + pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("MS TOTAL CX ADJ VERT computed!\n"); + + ret = parseProductionTestLimits(path_limits, + &limit_file, + MS_TOTAL_CX_ADJV_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + if (ret < 0 || (trows != totCompData.header.force_node - + 1 || tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_ADJV_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdjTotal(total_adjvert, + totCompData.header. + force_node - 1, + totCompData.header. + sense_node - 1, + thresholds_max); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj MS TOTAL CX ADJV failed... ERROR COUNT = %d\n", + ret); + pr_err("MS TOTAL CX ADJ HORIZ TEST:.................FAIL\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS TOTAL CX ADJ VERT TEST:.................OK\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(total_adjvert); + total_adjvert = NULL; + } else + pr_info("MS TOTAL CX ADJ TEST:.................SKIPPED\n"); + + kfree(totCompData.node_data); + totCompData.node_data = NULL; + } else + pr_info("MS TOTAL CX TEST:.................SKIPPED\n"); + + + + if ((todo->MutualKeyCx1 | todo->MutualKeyCx2 | + todo->MutualKeyCxTotal) == 1) { + ret = production_test_ms_key_cx(path_limits, stop_on_fail, + todo); + if (ret < 0) { + count_fail += 1; + pr_err("production_test_data: production_test_ms_key_cx failed... ERROR = %08X\n", + ret); + pr_err("MS CX testes finished!.................FAILED fails_count = %d\n\n", + count_fail); + return ret; + } + } else + pr_info("MS KEY CX TEST:.................SKIPPED\n"); + +ERROR: + + if (count_fail == 0) { + pr_info("MS CX testes finished!.................OK\n"); + kfree(msCompData.node_data); + msCompData.node_data = NULL; + return OK; + } else { + print_frame_i8("MS Init Data (Cx2) =", array1dTo2d_i8( + msCompData.node_data, + msCompData.node_data_size, + msCompData.header.sense_node), + msCompData.header.force_node, + msCompData.header.sense_node); + print_frame_short(" TOT MS Init Data (Cx) =", array1dTo2d_short( + totCompData.node_data, + totCompData.node_data_size, + totCompData.header.sense_node), + totCompData.header.force_node, + totCompData.header.sense_node); + pr_err("MS CX testes finished!.................FAILED fails_count = %d\n\n", + count_fail); + if (thresholds != NULL) + kfree(thresholds); + if (thresholds_min != NULL) + kfree(thresholds_min); + if (thresholds_max != NULL) + kfree(thresholds_max); + if (adjhor != NULL) + kfree(adjhor); + if (adjvert != NULL) + kfree(adjvert); + if (totCompData.node_data != NULL) + kfree(totCompData.node_data); + if (total_adjhor != NULL) + kfree(total_adjhor); + if (total_adjvert != NULL) + kfree(total_adjvert); + if (msCompData.node_data != NULL) + kfree(msCompData.node_data); + return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA; + } + +ERROR_LIMITS: + if (thresholds != NULL) + kfree(thresholds); + if (thresholds_min != NULL) + kfree(thresholds_min); + if (thresholds_max != NULL) + kfree(thresholds_max); + if (adjhor != NULL) + kfree(adjhor); + if (adjvert != NULL) + kfree(adjvert); + if (totCompData.node_data != NULL) + kfree(totCompData.node_data); + if (total_adjhor != NULL) + kfree(total_adjhor); + if (total_adjvert != NULL) + kfree(total_adjvert); + if (msCompData.node_data != NULL) + kfree(msCompData.node_data); + return ret; +} + +/** + * Perform all the tests selected in a TestTodo variable related to MS Init + * data of the keys + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ms_key_cx(char *path_limits, int stop_on_fail, + TestToDo *todo) +{ + int ret; + int count_fail = 0; + int num_keys = 0; + + int *thresholds = NULL; + int *thresholds_min = NULL; + int *thresholds_max = NULL; + int trows, tcolumns; + + MutualSenseData msCompData; + TotMutualSenseData totCompData; + + + short container; + + + /* MS CX TEST */ + pr_info("MS KEY CX Testes are starting...\n"); + + ret = readMutualSenseCompensationData(LOAD_CX_MS_KEY, &msCompData); + /* read MS compensation data */ + if (ret < 0) { + pr_err("production_test_data: readMutualSenseCompensationData failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + if (msCompData.header.force_node > msCompData.header.sense_node) + /* the meaningful data are only in the first row, + * the other rows are only a copy of the first one */ + num_keys = msCompData.header.force_node; + else + num_keys = msCompData.header.sense_node; + + pr_info("MS KEY CX1 TEST:\n"); + if (todo->MutualKeyCx1 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_KEY_CX1_MIN_MAX, &thresholds, + &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits MS_KEY_CX1_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + container = (short)msCompData.cx1; + ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], + thresholds[1]); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax MS CX1 failed... ERROR COUNT = %d\n", + ret); + pr_err("MS KEY CX1 TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS KEY CX1 TEST:.................OK\n\n"); + } else + pr_info("MS KEY CX1 TEST:.................SKIPPED\n\n"); + + kfree(thresholds); + thresholds = NULL; + + pr_info("MS KEY CX2 TEST:\n"); + if (todo->MutualKeyCx2 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_KEY_CX2_MAP_MIN, + &thresholds_min, &trows, + &tcolumns); + /* load min thresholds */ + if (ret < 0 || (trows != msCompData.header.force_node || + tcolumns != msCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_KEY_CX2_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_KEY_CX2_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load max thresholds */ + if (ret < 0 || (trows != msCompData.header.force_node || + tcolumns != msCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_KEY_CX2_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMap(msCompData.node_data, + msCompData.header.force_node, + msCompData.header.sense_node, + thresholds_min, thresholds_max); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap MS KEY CX2 failed... ERROR COUNT = %d\n", + ret); + pr_err("MS KEY CX2 TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS KEY CX2 TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("MS CX2 TEST:.................SKIPPED\n\n"); + + /* START OF TOTAL CHECK */ + pr_info("MS KEY TOTAL CX TEST:\n"); + + if (todo->MutualKeyCxTotal == 1) { + ret = readTotMutualSenseCompensationData( + LOAD_PANEL_CX_TOT_MS_KEY, &totCompData); + if (ret < 0) { + pr_err("production_test_data: computeTotalCx failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_KEY_TOTAL_CX_MAP_MIN, + &thresholds_min, &trows, + &tcolumns); + /* load min thresholds */ + if (ret < 0 || (trows != totCompData.header.force_node || + tcolumns != totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_KEY_TOTAL_CX_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + MS_KEY_TOTAL_CX_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load max thresholds */ + if (ret < 0 || (trows != totCompData.header.force_node || + tcolumns != totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits MS_KEY_TOTAL_CX_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapTotal(totCompData.node_data, + totCompData.header.force_node, + totCompData.header.sense_node, + thresholds_min, thresholds_max); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap MS TOTAL KEY CX TEST failed... ERROR COUNT = %d\n", + ret); + pr_err("MS KEY TOTAL CX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("MS KEY TOTAL CX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + + kfree(totCompData.node_data); + totCompData.node_data = NULL; + } else + pr_info("MS KEY TOTAL CX TEST:.................SKIPPED\n"); + + +ERROR: + if (count_fail == 0) { + pr_info("MS KEY CX testes finished!.................OK\n"); + kfree(msCompData.node_data); + msCompData.node_data = NULL; + return OK; + } else { + print_frame_i8("MS Key Init Data (Cx2) =", array1dTo2d_i8( + msCompData.node_data, + msCompData.node_data_size, + msCompData.header.sense_node), + msCompData.header.force_node, + msCompData.header.sense_node); + pr_err("MS Key CX testes finished!.................FAILED fails_count = %d\n\n", + count_fail); + if (thresholds != NULL) + kfree(thresholds); + if (thresholds_min != NULL) + kfree(thresholds_min); + if (thresholds_max != NULL) + kfree(thresholds_max); + if (msCompData.node_data != NULL) + kfree(msCompData.node_data); + if (totCompData.node_data != NULL) + kfree(totCompData.node_data); + return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA; + } + +ERROR_LIMITS: + if (thresholds != NULL) + kfree(thresholds); + if (thresholds_min != NULL) + kfree(thresholds_min); + if (thresholds_max != NULL) + kfree(thresholds_max); + if (msCompData.node_data != NULL) + kfree(msCompData.node_data); + if (totCompData.node_data != NULL) + kfree(totCompData.node_data); + return ret; +} + +/** + * Perform all the test selected in a TestTodo variable related to SS raw data + *(touch, keys etc..) + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo) +{ + int ret; + int count_fail = 0; + int rows, columns; + + SelfSenseFrame ssRawFrame; + + int *thresholds = NULL; + int trows, tcolumns; + + /* SS TEST */ + pr_info("SS RAW Testes are starting...\n"); + + /************** Self Sense Test **************/ + + pr_info("Getting SS Frame...\n"); + ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_ACTIVE); + mdelay(WAIT_FOR_FRESH_FRAMES); + ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + ret |= getSSFrame3(SS_RAW, &ssRawFrame); + if (ret < 0) { + pr_err("production_test_data: getSSFrame failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + print_frame_short("SS Raw force frame =", + array1dTo2d_short( + ssRawFrame.force_data, + ssRawFrame.header.force_node, + 1), + ssRawFrame.header.force_node, 1); + print_frame_short("SS Raw sense frame =", + array1dTo2d_short( + ssRawFrame.sense_data, + ssRawFrame.header.sense_node, + ssRawFrame.header.sense_node), + 1, ssRawFrame.header.sense_node); + + /* SS RAW (PROXIMITY) FORCE TEST */ + pr_info("SS RAW FORCE TEST:\n"); + + + + if (todo->SelfForceRaw == 1 || todo->SelfForceRawGap == 1) { + columns = 1; /* there are no data for the sense channels + * because is a force frame */ + rows = ssRawFrame.header.force_node; + + pr_info("SS RAW FORCE MIN MAX TEST:\n"); + if (todo->SelfForceRaw == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_FORCE_MIN_MAX, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMinMax(ssRawFrame.force_data, rows, + columns, thresholds[0], + thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS RAW FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS RAW (PROXIMITY) FORCE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW FORCE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW FORCE MIN MAX TEST:.................SKIPPED\n\n"); + + pr_info("SS RAW FORCE GAP TEST:\n"); + if (todo->SelfForceRawGap == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_FORCE_GAP, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_GAP failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsGap(ssRawFrame.force_data, rows, + columns, thresholds[0]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsGap SS RAW FORCE GAP failed... ERROR = %08X\n", + ret); + pr_err("SS RAW FORCE GAP TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW FORCE GAP TEST:.................OK\n\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW FORCE GAP TEST:.................SKIPPED\n\n"); + + kfree(ssRawFrame.force_data); + ssRawFrame.force_data = NULL; + } else + pr_info("SS RAW FORCE TEST:.................SKIPPED\n\n"); + + /* SS RAW (PROXIMITY) SENSE TEST */ + pr_info("SS RAW SENSE TEST:\n"); + + if (todo->SelfSenseRaw == 1 || todo->SelfSenseRawGap == 1) { + columns = ssRawFrame.header.sense_node; + rows = 1;/* there are no data for the force channels + * because is a sense frame */ + + pr_info("SS RAW SENSE MIN MAX TEST:\n"); + if (todo->SelfSenseRaw == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_SENSE_MIN_MAX, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMinMax(ssRawFrame.sense_data, rows, + columns, thresholds[0], + thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS RAW SENSE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS RAW SENSE MIN MAX TEST:.................FAIL\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW SENSE MIN MAX TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW SENSE MIN MAX TEST:.................SKIPPED\n"); + + pr_info("SS RAW SENSE GAP TEST:\n"); + if (todo->SelfSenseRawGap == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_SENSE_GAP, + &thresholds, &trows, + &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_GAP failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsGap(ssRawFrame.sense_data, rows, + columns, thresholds[0]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsGap SS RAW SENSE GAP failed... ERROR = %08X\n", + ret); + pr_err("SS RAW SENSE GAP TEST:.................FAIL\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW SENSE GAP TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW SENSE GAP TEST:.................SKIPPED\n"); + + kfree(ssRawFrame.sense_data); + ssRawFrame.sense_data = NULL; + } + + ret = production_test_ss_raw_lp(path_limits, stop_on_fail, todo); + if (ret < OK) { + pr_err("production_test_data: production_test_ss_raw_lp failed... ERROR = %08X\n", + ret); + count_fail += 1; + } + + if (count_fail == 0) { + pr_info("SS RAW testes finished!.................OK\n\n"); + return OK; + } else { + pr_err("SS RAW testes finished!.................FAILED fails_count = %d\n\n", + count_fail); + return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA; + } + +ERROR_LIMITS: + if (ssRawFrame.force_data != NULL) + kfree(ssRawFrame.force_data); + if (ssRawFrame.sense_data != NULL) + kfree(ssRawFrame.sense_data); + if (thresholds != NULL) + kfree(thresholds); + return ret; +} + + +/** + * Perform all the test selected in a TestTodo variable related to SS raw data + * low power + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ss_raw_lp(char *path_limits, int stop_on_fail, + TestToDo *todo) +{ + int ret; + int count_fail = 0; + int rows, columns; + + SelfSenseFrame ssRawFrame; + + int *thresholds = NULL; + int trows, tcolumns; + + /* SS TEST */ + pr_info("SS RAW LP Testes are starting...\n"); + + /************** Self Sense Test **************/ + + pr_info("Getting SS LP Frame...\n"); + ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_LP_DETECT); + mdelay(WAIT_FOR_FRESH_FRAMES); + ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + ret |= getSSFrame3(SS_RAW, &ssRawFrame); + if (ret < 0) { + pr_err("production_test_data: getSSFrame failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + print_frame_short("SS Raw LP force frame =", + array1dTo2d_short( + ssRawFrame.force_data, + ssRawFrame.header.force_node, 1), + ssRawFrame.header.force_node, 1); + print_frame_short("SS Raw LP sense frame =", + array1dTo2d_short( + ssRawFrame.sense_data, + ssRawFrame.header.sense_node, + ssRawFrame.header.sense_node), + 1, ssRawFrame.header.sense_node); + + /* SS RAW (PROXIMITY) FORCE TEST */ + pr_info("SS RAW LP FORCE TEST:\n"); + + if (todo->SelfForceRawLP == 1 || todo->SelfForceRawGapLP == 1) { + columns = 1; /* there are no data for the sense channels + * because is a force frame */ + rows = ssRawFrame.header.force_node; + + pr_info("SS RAW LP FORCE MIN MAX TEST:\n"); + if (todo->SelfForceRawLP == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_LP_FORCE_MIN_MAX, + &thresholds, + &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMinMax(ssRawFrame.force_data, rows, + columns, thresholds[0], + thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS RAW FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS RAW LP FORCE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW LP FORCE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW LP FORCE MIN MAX TEST:.................SKIPPED\n\n"); + + pr_info("SS RAW LP FORCE GAP TEST:\n"); + if (todo->SelfForceRawGapLP == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_LP_FORCE_GAP, + &thresholds, &trows, + &tcolumns); + if (ret < OK || (trows != 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_GAP failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsGap(ssRawFrame.force_data, rows, + columns, thresholds[0]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsGap SS RAW FORCE GAP failed... ERROR = %08X\n", + ret); + pr_err("SS RAW LP FORCE GAP TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW LP FORCE GAP TEST:.................OK\n\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW LP FORCE GAP TEST:.................SKIPPED\n\n"); + + kfree(ssRawFrame.force_data); + ssRawFrame.force_data = NULL; + } else + pr_info("SS RAW LP FORCE TEST:.................SKIPPED\n\n"); + + /* SS RAW (PROXIMITY) SENSE TEST */ + pr_info("SS RAW LP SENSE TEST:\n"); + + if (todo->SelfSenseRawLP == 1 || todo->SelfSenseRawGapLP == 1) { + columns = ssRawFrame.header.sense_node; + rows = 1;/* there are no data for the force channels + * because is a sense frame */ + + pr_info("SS RAW LP SENSE MIN MAX TEST:\n"); + if (todo->SelfSenseRawLP == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_LP_SENSE_MIN_MAX, + &thresholds, + &trows, &tcolumns); + if (ret < OK || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMinMax(ssRawFrame.sense_data, rows, + columns, thresholds[0], + thresholds[1]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS RAW SENSE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS RAW LP SENSE MIN MAX TEST:.................FAIL\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW SENSE MIN MAX TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW LP SENSE MIN MAX TEST:.................SKIPPED\n"); + + pr_info("SS RAW LP SENSE GAP TEST:\n"); + if (todo->SelfSenseRawGapLP == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_RAW_LP_SENSE_GAP, + &thresholds, &trows, + &tcolumns); + if (ret < OK || (trows != 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_GAP failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsGap(ssRawFrame.sense_data, rows, + columns, thresholds[0]); + if (ret != OK) { + pr_err("production_test_data: checkLimitsGap SS RAW SENSE GAP failed... ERROR = %08X\n", + ret); + pr_err("SS RAW LP SENSE GAP TEST:.................FAIL\n"); + count_fail += 1; + if (stop_on_fail) { + ret = ERROR_PROD_TEST_DATA | + ERROR_TEST_CHECK_FAIL; + goto ERROR_LIMITS; + } + } else + pr_info("SS RAW LP SENSE GAP TEST:.................OK\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS RAW LP SENSE GAP TEST:.................SKIPPED\n"); + + kfree(ssRawFrame.sense_data); + ssRawFrame.sense_data = NULL; + } + + if (count_fail == 0) { + pr_info("SS RAW LP testes finished!.................OK\n\n"); + return OK; + } else { + pr_err("SS RAW LP testes finished!.................FAILED fails_count = %d\n\n", + count_fail); + return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA; + } + +ERROR_LIMITS: + if (ssRawFrame.force_data != NULL) + kfree(ssRawFrame.force_data); + if (ssRawFrame.sense_data != NULL) + kfree(ssRawFrame.sense_data); + if (thresholds != NULL) + kfree(thresholds); + return ret; +} + +/** + * Perform all the tests selected in a TestTodo variable related to SS Init + * data (touch, keys etc..) + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_ss_ix_cx(char *path_limits, int stop_on_fail, + TestToDo *todo) +{ + int ret; + int count_fail = 0; + + int *thresholds = NULL; + int trows, tcolumns; + int *thresholds_min = NULL; + int *thresholds_max = NULL; + + SelfSenseData ssCompData; + TotSelfSenseData totCompData; + + u8 *adjhor = NULL; + u8 *adjvert = NULL; + + short container; + + u16 *total_adjhor = NULL; + u16 *total_adjvert = NULL; + + pr_info("SS IX CX testes are starting...\n"); + ret = readSelfSenseCompensationData(LOAD_CX_SS_TOUCH, &ssCompData); + /* read the SS compensation data */ + if (ret < 0) { + pr_err("production_test_data: readSelfSenseCompensationData failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + return ret | ERROR_PROD_TEST_DATA; + } + + ret = readTotSelfSenseCompensationData(LOAD_PANEL_CX_TOT_SS_TOUCH, + &totCompData); + /* read the TOT SS compensation data */ + if (ret < 0) { + pr_err("production_test_data: readTotSelfSenseCompensationData failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + kfree(ssCompData.ix2_fm); + kfree(ssCompData.ix2_sn); + kfree(ssCompData.cx2_fm); + kfree(ssCompData.cx2_sn); + return ret | ERROR_PROD_TEST_DATA; + } + + /************* SS FORCE IX **************/ + /* SS IX1 FORCE TEST */ + pr_info("SS IX1 FORCE TEST:\n"); + if (todo->SelfForceIx1 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX1_FORCE_MIN_MAX, + &thresholds, &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX1_FORCE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + container = (short)ssCompData.f_ix1; + ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], + thresholds[1]); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS IX1 FORCE TEST failed... ERROR COUNT = %d\n", + ret); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS IX1 FORCE TEST:.................OK\n\n"); + } else + pr_info("SS IX1 FORCE TEST:.................SKIPPED\n\n"); + + kfree(thresholds); + thresholds = NULL; + /* SS IX2 FORCE TEST */ + pr_info("SS IX2 FORCE MIN MAX TEST:\n"); + if (todo->SelfForceIx2 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX2_FORCE_MAP_MIN, + &thresholds_min, &trows, + &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != ssCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_FORCE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX2_FORCE_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != ssCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_FORCE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapFromU(ssCompData.ix2_fm, + ssCompData.header.force_node, 1, + thresholds_min, + thresholds_max); /* check the + * values with + * thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS IX2 FORCE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS IX2 FORCE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS IX2 FORCE MIN MAX TEST:.................SKIPPED\n\n"); + + pr_info("SS IX2 FORCE ADJ TEST:\n"); + if (todo->SelfForceIx2Adj == 1) { + /* SS IX2 FORCE ADJV TEST */ + pr_info("SS IX2 FORCE ADJVERT TEST:\n"); + ret = computeAdjVertFromU(ssCompData.ix2_fm, + ssCompData.header.force_node, 1, + &adjvert); + if (ret < 0) { + pr_err("production_test_data: computeAdjVert SS IX2 FORCE ADJV failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS IX2 FORCE ADJV computed!\n"); + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX2_FORCE_ADJV_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); /* load the max + * thresholds */ + if (ret < 0 || (trows != ssCompData.header.force_node - 1 || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_FORCE_ADJV_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdj(adjvert, ssCompData.header.force_node - + 1, 1, thresholds_max); /* check the + * values with + * thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS IX2 FORCE ADJV TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS IX2 FORCE ADJV TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(adjvert); + adjvert = NULL; + } else + pr_info("SS IX2 FORCE ADJ TEST:.................SKIPPED\n\n"); + + /* SS TOTAL FORCE IX */ + pr_info("SS TOTAL IX FORCE TEST:\n"); + if (todo->SelfForceIxTotal == 1 || todo->SelfForceIxTotalAdj == 1) { + pr_info("SS TOTAL IX FORCE MIN MAX TEST:\n"); + if (todo->SelfForceIxTotal == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_IX_FORCE_MAP_MIN, + &thresholds_min, + &trows, &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_IX_FORCE_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapTotalFromU(totCompData.ix_fm, + totCompData.header. + force_node, 1, + thresholds_min, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS TOTAL IX FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL IX FORCE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL IX FORCE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS TOTAL IX FORCE MIN MAX TEST:.................SKIPPED\n"); + + pr_info("SS TOTAL IX FORCE ADJ TEST:\n"); + if (todo->SelfForceIxTotalAdj == 1) { + /* SS TOTAL IX FORCE ADJV TEST */ + pr_info("SS TOTAL IX FORCE ADJVERT TEST:\n"); + ret = computeAdjVertTotalFromU(totCompData.ix_fm, + totCompData.header. + force_node, 1, + &total_adjvert); + if (ret < 0) { + pr_err("production_test_data: computeAdjVert SS TOTAL IX FORCE ADJV failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS TOTAL IX FORCE ADJV computed!\n"); + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_IX_FORCE_ADJV_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != totCompData.header.force_node - + 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_ADJV_MAP_MAX... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdjTotal(total_adjvert, + totCompData.header. + force_node - 1, 1, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS TOTAL IX FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL IX FORCE ADJV TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL IX FORCE ADJV TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(total_adjvert); + total_adjvert = NULL; + } else + pr_info("SS TOTAL IX FORCE ADJ TEST:.................SKIPPED\n"); + } else + pr_info("SS TOTAL IX FORCE TEST:.................SKIPPED\n\n"); + + + /************** SS SENSE IX **************/ + /* SS IX1 SENSE TEST */ + pr_info("SS IX1 SENSE TEST:\n"); + if (todo->SelfSenseIx1 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX1_SENSE_MIN_MAX, + &thresholds, &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX1_SENSE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + container = (short)ssCompData.s_ix1; + ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], + thresholds[1]); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS IX1 SENSE TEST failed... ERROR COUNT = %d\n", + ret); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS IX1 SENSE TEST:.................OK\n\n"); + } else + pr_info("SS IX1 SENSE TEST:.................SKIPPED\n\n"); + + kfree(thresholds); + thresholds = NULL; + /* SS IX2 SENSE TEST */ + pr_info("SS IX2 SENSE MIN MAX TEST:\n"); + if (todo->SelfSenseIx2 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX2_SENSE_MAP_MIN, + &thresholds_min, &trows, + &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + ssCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX2_SENSE_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + ssCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapFromU(ssCompData.ix2_sn, 1, + ssCompData.header.sense_node, + thresholds_min, thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS IX2 SENSE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS IX2 SENSE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS IX2 SENSE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS IX2 SENSE MIN MAX TEST:.................SKIPPED\n\n"); + + pr_info("SS IX2 SENSE ADJ TEST:\n"); + if (todo->SelfSenseIx2Adj == 1) { + /* SS IX2 SENSE ADJH TEST */ + pr_info("SS IX2 SENSE ADJHORIZ TEST:\n"); + ret = computeAdjHorizFromU(ssCompData.ix2_sn, 1, + ssCompData.header.sense_node, + &adjhor); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz SS IX2 SENSE ADJH failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS IX2 SENSE ADJ HORIZ computed!\n"); + + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_IX2_SENSE_ADJH_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + ssCompData.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_ADJH_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdj(adjhor, 1, + ssCompData.header.sense_node - 1, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj SS IX2 SENSE ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("SS IX2 SENSE ADJH TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS IX2 SENSE ADJH TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(adjhor); + adjhor = NULL; + } else + pr_info("SS IX2 SENSE ADJ TEST:.................SKIPPED\n"); + + /* SS TOTAL IX SENSE */ + pr_info("SS TOTAL IX SENSE TEST:\n"); + if (todo->SelfSenseIxTotal == 1 || todo->SelfSenseIxTotalAdj == 1) { + pr_info("SS TOTAL IX SENSE MIN MAX TEST:\n"); + if (todo->SelfSenseIxTotal == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_IX_SENSE_MAP_MIN, + &thresholds_min, + &trows, &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_IX_SENSE_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapTotalFromU(totCompData.ix_sn, 1, + totCompData.header. + sense_node, + thresholds_min, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS TOTAL IX SENSE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL IX SENSE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL IX SENSE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS TOTAL IX SENSE MIN MAX TEST:.................SKIPPED\n"); + + + pr_info("SS TOTAL IX SENSE ADJ TEST:\n"); + if (todo->SelfSenseIxTotalAdj == 1) { + /* SS TOTAL IX SENSE ADJH TEST */ + pr_info("SS TOTAL IX SENSE ADJHORIZ TEST:\n"); + ret = computeAdjHorizTotalFromU(totCompData.ix_sn, 1, + totCompData.header. + sense_node, + &total_adjhor); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz SS TOTAL IX SENSE ADJH failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS TOTAL IX SENSE ADJ HORIZ computed!\n"); + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_IX_SENSE_ADJH_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + totCompData.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_ADJH_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdjTotal(total_adjhor, 1, + totCompData.header. + sense_node - 1, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj SS TOTAL IX SENSE ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL IX SENSE ADJH TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL IX SENSE ADJH TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(total_adjhor); + total_adjhor = NULL; + } else + pr_info("SS TOTAL IX SENSE ADJ TEST:.................SKIPPED\n"); + } else + pr_info("SS TOTAL IX SENSE TEST:.................SKIPPED\n"); + + /************* SS SENSE CX **************/ + /* SS CX1 FORCE TEST */ + pr_info("SS CX1 FORCE TEST:\n"); + if (todo->SelfForceCx1 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX1_FORCE_MIN_MAX, + &thresholds, &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX1_FORCE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + container = (short)ssCompData.f_cx1; + ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], + thresholds[1]); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS CX1 FORCE TEST failed... ERROR COUNT = %d\n", + ret); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS CX1 FORCE TEST:.................OK\n\n"); + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS CX1 FORCE TEST:.................SKIPPED\n\n"); + + /* SS CX2 FORCE TEST */ + pr_info("SS CX2 FORCE MIN MAX TEST:\n"); + if (todo->SelfForceCx2 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX2_FORCE_MAP_MIN, + &thresholds_min, &trows, + &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != ssCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX2_FORCE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX2_FORCE_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != ssCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX2_FORCE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMap(ssCompData.cx2_fm, + ssCompData.header.force_node, 1, + thresholds_min, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS CX2 FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS CX2 FORCE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS CX2 FORCE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS CX2 FORCE MIN MAX TEST:.................SKIPPED\n"); + + pr_info("SS CX2 FORCE ADJ TEST:\n"); + if (todo->SelfForceCx2Adj == 1) { + /* SS CX2 FORCE ADJV TEST */ + pr_info("SS CX2 FORCE ADJVERT TEST:\n"); + ret = computeAdjVert(ssCompData.cx2_fm, + ssCompData.header.force_node, 1, &adjvert); + /* compute the ADJV for CX2 FORCE */ + if (ret < 0) { + pr_err("production_test_data: computeAdjVert SS CX2 FORCE ADJV failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS CX2 FORCE ADJV computed!\n"); + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX2_FORCE_ADJV_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != ssCompData.header.force_node - 1 || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX2_FORCE_ADJV_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdj(adjvert, ssCompData.header.force_node - + 1, 1, thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS CX2 FORCE ADJV TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS CX2 FORCE ADJV TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(adjvert); + adjvert = NULL; + } else + pr_info("SS CX2 FORCE ADJ TEST:.................SKIPPED\n\n"); + + /* SS TOTAL CX FORCE */ + pr_info("SS TOTAL CX FORCE TEST:\n"); + if (todo->SelfForceCxTotal == 1 || todo->SelfForceCxTotalAdj == 1) { + pr_info("SS TOTAL CX FORCE MIN MAX TEST:\n"); + if (todo->SelfForceCxTotal == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_CX_FORCE_MAP_MIN, + &thresholds_min, + &trows, &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_CX_FORCE_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != + totCompData.header.force_node || + tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapTotal(totCompData.cx_fm, + totCompData.header.force_node, + 1, thresholds_min, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS TOTAL FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL FORCE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL FORCE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS TOTAL CX FORCE MIN MAX TEST:.................SKIPPED\n"); + + /* SS TOTAL CX FORCE ADJV TEST */ + pr_info("SS TOTAL CX FORCE ADJ TEST:\n"); + if (todo->SelfForceCxTotalAdj == 1) { + pr_info("SS TOTAL CX FORCE ADJVERT TEST:\n"); + ret = computeAdjVertTotal(totCompData.cx_fm, + totCompData.header.force_node, + 1, &total_adjvert); + /* compute the ADJV for CX2 FORCE */ + if (ret < 0) { + pr_err("production_test_data: computeAdjVert SS TOTAL CX FORCE ADJV failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS TOTAL CX FORCE ADJV computed!\n"); + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_CX_FORCE_ADJV_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != totCompData.header.force_node - + 1 || tcolumns != 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_ADJV_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdjTotal(total_adjvert, + totCompData.header. + force_node - 1, 1, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS TOTAL CX FORCE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL CX FORCE ADJV TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL CX FORCE ADJV TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(total_adjvert); + total_adjvert = NULL; + } else + pr_info("SS TOTAL CX FORCE ADJ TEST:.................SKIPPED\n"); + } else + pr_info("SS TOTAL CX FORCE TEST:.................SKIPPED\n\n"); + + + + /************* SS SENSE CX *************/ + /* SS CX1 SENSE TEST */ + pr_info("SS CX1 SENSE TEST:\n"); + if (todo->SelfSenseCx1 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX1_SENSE_MIN_MAX, + &thresholds, &trows, &tcolumns); + if (ret < 0 || (trows != 1 || tcolumns != 2)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX1_SENSE_MIN_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + container = (short)ssCompData.s_cx1; + ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], + thresholds[1]); + /* check the limits */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMinMax SS CX1 SENSE TEST failed... ERROR COUNT = %d\n", + ret); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS CX1 SENSE TEST:.................OK\n\n"); + + kfree(thresholds); + thresholds = NULL; + } else + pr_info("SS CX1 SENSE TEST:.................SKIPPED\n\n"); + + + /* SS CX2 SENSE TEST */ + pr_info("SS CX2 SENSE MIN MAX TEST:\n"); + if (todo->SelfSenseCx2 == 1) { + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX2_SENSE_MAP_MIN, + &thresholds_min, &trows, + &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + ssCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX2_SENSE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX2_SENSE_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + ssCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_CX2_SENSE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMap(ssCompData.cx2_sn, 1, + ssCompData.header.sense_node, + thresholds_min, thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS CX2 SENSE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS CX2 SENSE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS CX2 SENSE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS CX2 SENSE MIN MAX TEST:.................SKIPPED\n"); + + pr_info("SS CX2 SENSE ADJ TEST:\n"); + if (todo->SelfSenseCx2Adj == 1) { + /* SS CX2 SENSE ADJH TEST */ + pr_info("SS CX2 SENSE ADJHORIZ TEST:\n"); + ret = computeAdjHoriz(ssCompData.cx2_sn, 1, + ssCompData.header.sense_node, &adjhor); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz SS CX2 SENSE ADJH failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS CX2 SENSE ADJH computed!\n"); + + + ret = parseProductionTestLimits(path_limits, &limit_file, + SS_CX2_SENSE_ADJH_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + ssCompData.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdj(adjhor, 1, + ssCompData.header.sense_node - 1, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj SS CX2 SENSE ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("SS CX2 SENSE ADJH TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS CX2 SENSE ADJH TEST:.................OK\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(adjhor); + adjhor = NULL; + } else + pr_info("SS CX2 SENSE ADJ TEST:.................SKIPPED\n\n"); + + /* SS TOTAL CX SENSE */ + pr_info("SS TOTAL CX SENSE TEST:\n"); + if (todo->SelfSenseCxTotal == 1 || todo->SelfSenseCxTotalAdj == 1) { + pr_info("SS TOTAL CX SENSE MIN MAX TEST:\n"); + if (todo->SelfSenseCxTotal == 1) { + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_CX_SENSE_MAP_MIN, + &thresholds_min, + &trows, &tcolumns); + /* load the min thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_MAP_MIN failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_CX_SENSE_MAP_MAX, + &thresholds_max, + &trows, &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + totCompData.header.sense_node)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapTotal(totCompData.cx_sn, 1, + totCompData.header.sense_node, + thresholds_min, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMap SS TOTAL CX SENSE failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL CX SENSE MIN MAX TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL CX SENSE MIN MAX TEST:.................OK\n\n"); + + kfree(thresholds_min); + thresholds_min = NULL; + kfree(thresholds_max); + thresholds_max = NULL; + } else + pr_info("SS TOTAL CX SENSE MIN MAX TEST:.................SKIPPED\n"); + + + /* SS TOTAL IX SENSE ADJH TEST */ + pr_info("SS TOTAL CX SENSE ADJ TEST:\n"); + if (todo->SelfSenseCxTotalAdj == 1) { + pr_info("SS TOTAL CX SENSE ADJHORIZ TEST:\n"); + ret = computeAdjHorizTotal(totCompData.cx_sn, 1, + totCompData.header.sense_node, + &total_adjhor); + if (ret < 0) { + pr_err("production_test_data: computeAdjHoriz SS TOTAL CX SENSE ADJH failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + pr_info("SS TOTAL CX SENSE ADJ HORIZ computed!\n"); + + + ret = parseProductionTestLimits(path_limits, + &limit_file, + SS_TOTAL_CX_SENSE_ADJH_MAP_MAX, + &thresholds_max, &trows, + &tcolumns); + /* load the max thresholds */ + if (ret < 0 || (trows != 1 || tcolumns != + totCompData.header.sense_node - 1)) { + pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_ADJH_MAP_MAX failed... ERROR %08X\n", + ERROR_PROD_TEST_DATA); + ret |= ERROR_PROD_TEST_DATA; + goto ERROR_LIMITS; + } + + ret = checkLimitsMapAdjTotal(total_adjhor, 1, + totCompData.header. + sense_node - 1, + thresholds_max); + /* check the values with thresholds */ + if (ret != OK) { + pr_err("production_test_data: checkLimitsMapAdj SS TOTAL CX SENSE ADJH failed... ERROR COUNT = %d\n", + ret); + pr_err("SS TOTAL CX SENSE ADJH TEST:.................FAIL\n\n"); + count_fail += 1; + if (stop_on_fail) + goto ERROR; + } else + pr_info("SS TOTAL CX SENSE ADJH TEST:.................OK\n\n"); + + kfree(thresholds_max); + thresholds_max = NULL; + kfree(total_adjhor); + total_adjhor = NULL; + } else + pr_info("SS TOTAL CX SENSE ADJ TEST:.................SKIPPED\n"); + } else + pr_info("SS TOTAL CX SENSE TEST:.................SKIPPED\n"); + + + +ERROR: + if (count_fail == 0) { + kfree(ssCompData.ix2_fm); + ssCompData.ix2_fm = NULL; + kfree(ssCompData.ix2_sn); + ssCompData.ix2_sn = NULL; + kfree(ssCompData.cx2_fm); + ssCompData.cx2_fm = NULL; + kfree(ssCompData.cx2_sn); + ssCompData.cx2_sn = NULL; + kfree(totCompData.ix_fm); + totCompData.ix_fm = NULL; + kfree(totCompData.ix_sn); + totCompData.ix_sn = NULL; + kfree(totCompData.cx_fm); + totCompData.cx_fm = NULL; + kfree(totCompData.cx_sn); + totCompData.cx_sn = NULL; + pr_info("SS IX CX testes finished!.................OK\n\n"); + return OK; + } else { + /* print all kind of data in just one row for readability reason */ + print_frame_u8("SS Init Data Ix2_fm = ", array1dTo2d_u8( + ssCompData.ix2_fm, + ssCompData.header.force_node, 1), + ssCompData.header.force_node, 1); + print_frame_i8("SS Init Data Cx2_fm = ", array1dTo2d_i8( + ssCompData.cx2_fm, + ssCompData.header.force_node, 1), + ssCompData.header.force_node, 1); + print_frame_u8("SS Init Data Ix2_sn = ", array1dTo2d_u8( + ssCompData.ix2_sn, + ssCompData.header.sense_node, + ssCompData.header.sense_node), 1, + ssCompData.header.sense_node); + print_frame_i8("SS Init Data Cx2_sn = ", array1dTo2d_i8( + ssCompData.cx2_sn, + ssCompData.header.sense_node, + ssCompData.header.sense_node), 1, + ssCompData.header.sense_node); + print_frame_u16("TOT SS Init Data Ix_fm = ", array1dTo2d_u16( + totCompData.ix_fm, + totCompData.header.force_node, 1), + totCompData.header.force_node, 1); + print_frame_short("TOT SS Init Data Cx_fm = ", + array1dTo2d_short(totCompData.cx_fm, + totCompData.header. + force_node, 1), + totCompData.header.force_node, 1); + print_frame_u16("TOT SS Init Data Ix_sn = ", array1dTo2d_u16( + totCompData.ix_sn, + totCompData.header.sense_node, + totCompData.header.sense_node), 1, + totCompData.header.sense_node); + print_frame_short("TOT SS Init Data Cx_sn = ", + array1dTo2d_short(totCompData.cx_sn, + totCompData.header. + sense_node, + totCompData.header. + sense_node), + 1, totCompData.header.sense_node); + pr_err("SS IX CX testes finished!.................FAILED fails_count = %d\n\n", + count_fail); + if (thresholds != NULL) + kfree(thresholds); + if (thresholds_min != NULL) + kfree(thresholds_min); + if (thresholds_max != NULL) + kfree(thresholds_max); + if (adjhor != NULL) + kfree(adjhor); + if (adjvert != NULL) + kfree(adjvert); + if (total_adjhor != NULL) + kfree(total_adjhor); + if (total_adjvert != NULL) + kfree(total_adjvert); + if (ssCompData.ix2_fm != NULL) + kfree(ssCompData.ix2_fm); + if (ssCompData.ix2_sn != NULL) + kfree(ssCompData.ix2_sn); + if (ssCompData.cx2_fm != NULL) + kfree(ssCompData.cx2_fm); + if (ssCompData.cx2_sn != NULL) + kfree(ssCompData.cx2_sn); + if (totCompData.ix_fm != NULL) + kfree(totCompData.ix_fm); + if (totCompData.ix_sn != NULL) + kfree(totCompData.ix_sn); + if (totCompData.cx_fm != NULL) + kfree(totCompData.cx_fm); + if (totCompData.cx_sn != NULL) + kfree(totCompData.cx_sn); + return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA; + } + +ERROR_LIMITS: + if (thresholds != NULL) + kfree(thresholds); + if (thresholds_min != NULL) + kfree(thresholds_min); + if (thresholds_max != NULL) + kfree(thresholds_max); + if (adjhor != NULL) + kfree(adjhor); + if (adjvert != NULL) + kfree(adjvert); + if (total_adjhor != NULL) + kfree(total_adjhor); + if (total_adjvert != NULL) + kfree(total_adjvert); + if (ssCompData.ix2_fm != NULL) + kfree(ssCompData.ix2_fm); + if (ssCompData.ix2_sn != NULL) + kfree(ssCompData.ix2_sn); + if (ssCompData.cx2_fm != NULL) + kfree(ssCompData.cx2_fm); + if (ssCompData.cx2_sn != NULL) + kfree(ssCompData.cx2_sn); + if (totCompData.ix_fm != NULL) + kfree(totCompData.ix_fm); + if (totCompData.ix_sn != NULL) + kfree(totCompData.ix_sn); + if (totCompData.cx_fm != NULL) + kfree(totCompData.cx_fm); + if (totCompData.cx_sn != NULL) + kfree(totCompData.cx_sn); + return ret; +} + +/** + * Perform a complete Data Test check of the IC + * @param path_limits name of Production Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param stop_on_fail if 1, the test flow stops at the first data check + * failure + * otherwise it keeps going performing all the selected test + * @param todo pointer to a TestToDo variable which select the test to do + * @return OK if success or an error code which specify the type of error + */ +int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo) +{ + int res = OK, ret; + + if (todo == NULL) { + pr_err("production_test_data: No TestToDo specified!! ERROR = %08X\n", + (ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_DATA)); + return ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_DATA; + } + + + pr_info("DATA Production test is starting...\n"); + + + ret = production_test_ms_raw(path_limits, stop_on_fail, todo); + res |= ret; + if (ret < 0) { + pr_err("production_test_data: production_test_ms_raw failed... ERROR = %08X\n", + ret); + if (stop_on_fail == 1) + goto END; + } + + + + ret = production_test_ms_cx(path_limits, stop_on_fail, todo); + res |= ret; + if (ret < 0) { + pr_err("production_test_data: production_test_ms_cx failed... ERROR = %08X\n", + ret); + if (stop_on_fail == 1) + goto END; + } + + + ret = production_test_ss_raw(path_limits, stop_on_fail, todo); + res |= ret; + if (ret < 0) { + pr_err("production_test_data: production_test_ss_raw failed... ERROR = %08X\n", + ret); + if (stop_on_fail == 1) + goto END; + } + + ret = production_test_ss_ix_cx(path_limits, stop_on_fail, todo); + res |= ret; + if (ret < 0) { + pr_err("production_test_data: production_test_ss_ix_cx failed... ERROR = %08X\n", + ret); + if (stop_on_fail == 1) + goto END; + } + +END: + freeLimitsFile(&limit_file); /* /< release the limit file loaded + * during the test */ + if (res < OK) + pr_err("DATA Production test failed!\n"); + else + pr_info("DATA Production test finished!\n"); + return res; +} + + +/*************** TP Sensitivity calibration API ********************/ + +/** + * Perform the Pre Calibration MS Test when the stimpad is down + * @param[out] frame pointer to the frame which will contain + * the average frame resulting from the test + * @param target reference value for the frame, each node should be + * around +-percentage% this value + * @param percentage percentage of the target value which define + * the valid interval for the frame, if <0 the test will be skipped + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_test_pre_cal_ms(MutualSenseFrame *finalFrame, short target, + int percentage) +{ + int ret = OK; + int count = 0, i = 0, j = 0; + short min, max; + MutualSenseFrame frame; + + finalFrame->node_data = NULL; + + + pr_info("%s: Start TP sensitivity MS Pre Cal...\n", __func__); + pr_info("%s: IMPORTANT!!! Stimpad should be on the display of the device!\n", + __func__); + ret = getMSFrame3(MS_STRENGTH, &frame); + if (ret < OK) { + pr_err("%s: can not read MS Frame... ERROR %08X\n", + __func__, ret); + goto ERROR; + } + + finalFrame->header = frame.header; + finalFrame->node_data_size = frame.node_data_size; + + finalFrame->node_data = (short *)kzalloc(frame.node_data_size * + sizeof(short), GFP_KERNEL); + if (finalFrame->node_data == NULL) { + pr_err("%s: can not allocate node_data ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + ret = ERROR_ALLOC | ERROR_GET_FRAME; + goto ERROR; + } + + /* collecting frames */ + do { + for (i = 0; i < finalFrame->node_data_size; i++) { + finalFrame->node_data[i] += (frame.node_data[i] * 10) / + SENS_TEST_NUM_FRAMES; + } + + if (frame.node_data != NULL) { + kfree(frame.node_data); + frame.node_data = NULL; + } + + count++; + + /* exclude one more reading at the end*/ + if (count < SENS_TEST_NUM_FRAMES) + ret = getMSFrame3(MS_STRENGTH, &frame); + } while ((count < SENS_TEST_NUM_FRAMES) && (ret >= OK)); + + if (ret < OK) { + pr_err("%s: Error while capturing the frame %d! ERROR %08X\n", + __func__, count, ret); + goto ERROR; + } + + ret = OK; + /* check against +-percentage% target */ + pr_info("%s: Computing average frame...\n", __func__); + + min = target - (target * percentage / 100); + max = target + (target * percentage / 100); + + for (i = 0; i < finalFrame->header.force_node; i++) { + for (j = 0; j < finalFrame->header.sense_node; j++) { + finalFrame->node_data[i * + finalFrame->header.sense_node + + j] /= 10; + /*if percentage is <0 skip this test, just collect data */ + if ((percentage > 0) && + ((finalFrame->node_data[i * finalFrame->header. + sense_node + + j] > + max) || + (finalFrame->node_data[i * + finalFrame->header. + sense_node + + j] < + min))) { + pr_err("%s: MS Force Node[%d, %d] = %d exceed limit [%d, %d]\n", + __func__, i, j, + finalFrame->node_data[i * + finalFrame + ->header. + sense_node + j], + min, max); + ret = ERROR_TEST_CHECK_FAIL; + } + } + } + + + /* print average frame in the log */ + print_frame_short("MS FS Mean =", + array1dTo2d_short( + finalFrame->node_data, + finalFrame->node_data_size, + finalFrame->header.sense_node), + finalFrame->header.force_node, + finalFrame->header.sense_node); + + if (ret != OK) + pr_err("%s: TP sensitivity MS Pre Cal test FAILED... ERROR %08X\n", + __func__, ret); + else + pr_info("%s: TP sensitivity MS Pre Cal FINISHED!\n", + __func__); + + return ret; + + +ERROR: + if (frame.node_data != NULL) { + kfree(frame.node_data); + frame.node_data = NULL; + } + + + if (finalFrame->node_data != NULL) { + kfree(finalFrame->node_data); + finalFrame->node_data = NULL; + } + + return ret; +} + + + +/** + * Perform the Pre Calibration SS Test when the stimpad is down + * @param[out] frame pointer to the frame which will contain the average frame + * resulting from the test + * @param target reference value for the frame, each node should be around + * +-percentage% this value + * @param percentage percentage of the target value which define the valid + * interval for the frame + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_test_pre_cal_ss(SelfSenseFrame *finalFrame, short target, + int percentage) +{ + int ret = OK; + int count = 0, i = 0; + short min, max; + SelfSenseFrame frame; + int *temp_force = NULL; + int *temp_sense = NULL; + + finalFrame->force_data = NULL; + finalFrame->sense_data = NULL; + + pr_info("%s: Start TP sensitivity SS Pre Cal...\n", __func__); + pr_info("%s: IMPORTANT!!! Stimpad should be on the display of the device!\n", + __func__); + ret = getSSFrame3(SS_STRENGTH, &frame); + if (ret < OK) { + pr_err("%s: can not read SS Frame... ERROR %08X\n", + __func__, ret); + goto ERROR; + } + + finalFrame->header = frame.header; + + finalFrame->force_data = (short *)kzalloc(frame.header.force_node * + sizeof(short), GFP_KERNEL); + temp_force = (int *)kzalloc(frame.header.force_node * + sizeof(int), GFP_KERNEL); + finalFrame->sense_data = (short *)kzalloc(frame.header.sense_node * + sizeof(short), GFP_KERNEL); + temp_sense = (int *)kzalloc(frame.header.sense_node * + sizeof(int), GFP_KERNEL); + if (finalFrame->force_data == NULL || + temp_force == NULL || + finalFrame->sense_data == NULL || + temp_sense == NULL) { + + pr_err("%s: can not allocate memory ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + ret = ERROR_ALLOC | ERROR_GET_FRAME; + goto ERROR; + } + + /* collecting frames */ + do { + for (i = 0; i < finalFrame->header.force_node; i++) + temp_force[i] += frame.force_data[i]; + + for (i = 0; i < finalFrame->header.sense_node; i++) + temp_sense[i] += frame.sense_data[i]; + + count++; + + if (frame.force_data != NULL) { + kfree(frame.force_data); + frame.force_data = NULL; + } + if (frame.sense_data != NULL) { + kfree(frame.sense_data); + frame.sense_data = NULL; + } + + /* exclude one more reading at the end*/ + if (count < SENS_TEST_NUM_FRAMES) + ret = getSSFrame3(SS_STRENGTH, &frame); + } while ((count < SENS_TEST_NUM_FRAMES) && (ret >= OK)); + + if (ret < OK) { + pr_err("%s: Error while capturing the frame %d! ERROR %08X\n", + __func__, count, ret); + goto ERROR; + } + + ret = OK; + + /* compute the average and check against +-percentage% target */ + min = target - (target * percentage / 100); + max = target + (target * percentage / 100); + + for (i = 0; i < finalFrame->header.force_node; i++) { + finalFrame->force_data[i] = temp_force[i] / + SENS_TEST_NUM_FRAMES; + if ((percentage > 0) && ((finalFrame->force_data[i] > max) || + (finalFrame->force_data[i] < min))) { + pr_err("%s: SS Force Node[%d] = %d exceed limit [%d, %d]\n", + __func__, i, finalFrame->force_data[i], + min, max); + ret = ERROR_TEST_CHECK_FAIL; + } + } + + for (i = 0; i < finalFrame->header.sense_node; i++) { + finalFrame->sense_data[i] = temp_sense[i] / + SENS_TEST_NUM_FRAMES; + if ((finalFrame->sense_data[i] > max) || + (finalFrame->sense_data[i] < min)) { + pr_err("%s: SS Sense Node[%d] = %d exceed limit [%d, %d]\n", + __func__, i, finalFrame->sense_data[i], + min, max); + ret = ERROR_TEST_CHECK_FAIL; + } + } + + /* print average frame in the log */ + print_frame_short("SS FS force Mean =", + array1dTo2d_short( + finalFrame->force_data, + finalFrame->header.force_node, + 1), + finalFrame->header.force_node, 1); + print_frame_short("SS FS sense Mean =", + array1dTo2d_short( + finalFrame->sense_data, + finalFrame->header.sense_node, + finalFrame->header.sense_node), + 1, finalFrame->header.sense_node); + + + kfree(temp_force); + temp_force = NULL; + + kfree(temp_sense); + temp_sense = NULL; + + if (ret < OK) + pr_err("%s: TP sensitivity SS Pre Cal test FAILED... ERROR %08X\n", + __func__, ret); + else { + pr_info("%s: TP sensitivity SS Pre Cal FINISHED!\n", + __func__); + ret = OK; + } + + return ret; + + +ERROR: + + kfree(temp_force); + temp_force = NULL; + + kfree(temp_sense); + temp_sense = NULL; + + kfree(frame.force_data); + frame.force_data = NULL; + + kfree(frame.sense_data); + frame.sense_data = NULL; + + kfree(finalFrame->force_data); + finalFrame->force_data = NULL; + + kfree(finalFrame->sense_data); + finalFrame->sense_data = NULL; + + return ret; +} + +/** + * Compute Digital gains for calibration + * @param frame pointer to the frame used as reference to compute the gains + * @param target reference target value for computing the gains + * @param saveGain if 1, will save the gain table into the chip otherwise will + * not save it + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_compute_gains(MutualSenseFrame *frame, short target, + int saveGain) +{ + int ret = OK; + int i = 0; + u8 gains[frame->node_data_size]; + + if ((frame->node_data == NULL) || (frame->node_data_size == 0)) { + pr_err("%s: Invalid frame data passed as argument! ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + memset(gains, 0, frame->node_data_size); + + pr_info("%s: Start to compute Digital Gains...\n", __func__); + for (i = 0; i < frame->node_data_size; i++) + gains[i] = ((target * 100) / frame->node_data[i]) > 255 ? + (u8)(255) : (u8)(((target * 100) / + frame->node_data[i])); + /* clamp the max value to 255 because gain is only one byte */ + + + /* print average frame in the log */ + print_frame_u8("MS Digital Gain =", + array1dTo2d_u8( + gains, + frame->node_data_size, + frame->header.sense_node), + frame->header.force_node, + frame->header.sense_node); + + + /* if(saveGain==1){ */ + /* write gains into the IC */ + ret = writeHostDataMemory(LOAD_SENS_CAL_COEFF, gains, + frame->header.force_node, + frame->header.sense_node, 0, 0, saveGain); + if (ret != OK) + pr_err("%s: impossible to write digital gains! ERROR %08X\n", + __func__, ret); + /* } */ + + if (ret < OK) + pr_err("%s: compute Digital Gains FAILED! ERROR %08X\n", + __func__, ret); + else { + pr_info("%s: compute Digital Gains FINISHED!\n", __func__); + ret = OK; + } + + return ret; +} + +/** + * Perform the Post Calibration MS Test when the stimpad is down + * @param[out] finalFrame pointer to the frame which will contain + * the average frame resulting from the test + * @param[out] deltas pointer to the frame which will contain + * the FS Uniform frame (worst_neighborhood/mean) + * @param target reference value for the frame, each node should be + * around +-percentage% this value + * @param percentage percentage of the target value which define + * the valid interval for the frame, if <0 the test will be skipped + * @param[out] mean_normal pointer to the variable which will contain the mean + * of the normal area + * @param[out] mean_edge pointer to the variable which will contain the mean of + * the edge area + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_test_post_cal_ms(MutualSenseFrame *finalFrame, + MutualSenseFrame *deltas, short target, + int percentage, int *mean_normal, + int *mean_edge) +{ + short currentNode; + int final_force_num; + int final_sense_num; + short *final_node; + int delta_sense_num; + short *delta_node; + short *delta; + short adjNode; + int ret = OK; + int i = 0, j = 0, min, max; + + + if ((finalFrame == NULL) || (deltas == NULL) || (mean_normal == NULL) || + (mean_edge == NULL)) { + pr_err("%s: Invalid arguments Passed! ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + *mean_normal = 0; + *mean_edge = 0; + + finalFrame->node_data = NULL; + deltas->node_data = NULL; + + pr_info("%s: Start TP sensitivity MS Post Cal...\n", __func__); + pr_info("%s: IMPORTANT!!! Stimpad should be on the display of the device!\n", + __func__); + + /* collect frames skipping the tests + print on the log */ + ret = tp_sensitivity_test_pre_cal_ms(finalFrame, target, -1); + if (ret < OK) { + pr_err("%s: can not collect MS Frame... ERROR %08X\n", + __func__, ret); + goto ERROR; + } + + + deltas->header = finalFrame->header; + deltas->node_data_size = finalFrame->node_data_size; + + deltas->node_data = (short *)kzalloc(deltas->node_data_size * + sizeof(short), GFP_KERNEL); + if (deltas->node_data == NULL) { + pr_err("%s: can not allocate deltas node_data ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + ret = ERROR_ALLOC | ERROR_GET_FRAME; + goto ERROR; + } + + /* compute the average of the whole panel and check against + * +-percentage% target */ + pr_info("%s: Computing average of whole panel and delta for each node...\n", + __func__); + + final_force_num = finalFrame->header.force_node; + final_sense_num = finalFrame->header.sense_node; + final_node = finalFrame->node_data; + delta_sense_num = deltas->header.sense_node; + delta_node = deltas->node_data; + + + for (i = 0; i < final_force_num; i++) { + for (j = 0; j < final_sense_num; j++) { + currentNode = finalFrame->node_data[i * + finalFrame->header. + sense_node + j]; + delta = &delta_node[i * delta_sense_num + j]; + + if ((i == 0) || + (i == (final_force_num - 1)) || + (j == 0) || + (j == (final_sense_num - 1))) { + /* edge nodes */ + *mean_edge += currentNode; + if ((i == 0) || + (i == final_force_num - 1)) { + /* need to check adj node up or down for + * nodes in the corners */ + if ((i == 0) && + ((j == 0) || + (j == final_sense_num - 1))) { + adjNode = currentNode - + final_node[(i + 1) * + final_sense_num + j]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + + if ((i == (final_force_num - 1)) && + ((j == 0) || + (j == final_sense_num - 1))) { + adjNode = currentNode - + final_node[(i - 1) * + final_sense_num + j]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + + /* scan the row */ + if ((j - 1) >= 0) { + adjNode = currentNode - + final_node[i * + final_sense_num + + (j - 1)]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + + if ((j + 1) < final_sense_num) { + adjNode = currentNode - + final_node[i * + final_sense_num + + (j + 1)]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + } + + if ((j == 0) || + (j == final_sense_num - 1)) { + /* scan the column */ + if ((i - 1) >= 0) { + adjNode = currentNode - + final_node[(i - 1) * + final_sense_num + j]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + + if ((i + 1) < final_force_num) { + adjNode = currentNode - + final_node[(i + 1) * + final_sense_num + j]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + } + } else { + /*normal nodes */ + *mean_normal += currentNode; + + /* picking up the worst difference between + * one pixel and its neighbors */ + if ((i - 1) >= 1) { + adjNode = currentNode - + final_node[(i - 1) * + final_sense_num + j]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + + if ((i + 1) < (final_force_num - 1)) { + adjNode = currentNode - + final_node[(i + 1) * + final_sense_num + j]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + if ((j - 1) >= 1) { + adjNode = currentNode - + final_node[i * + final_sense_num + (j - 1)]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + + if ((j + 1) < (final_sense_num - 1)) { + adjNode = currentNode - + final_node[i * + final_sense_num + (j + 1)]; + if (abs(adjNode) > *delta) + *delta = abs(adjNode); + } + } + } + } + + *mean_normal /= (finalFrame->header.force_node - 2) * + (finalFrame->header.sense_node - 2); + *mean_edge /= (finalFrame->header.force_node * 2) + + (finalFrame->header.sense_node - 2) * 2; + + pr_info("%s: Normal Frame average = %d\n", __func__, *mean_normal); + pr_info("%s: Edge Frame average = %d\n", __func__, *mean_edge); + /* compute the average and check against +-% target */ + min = target - (target * percentage / 100); + max = target + (target * percentage / 100); + + if ((percentage > 0) && ((*mean_normal < min) || (*mean_normal > + max))) { + pr_err("%s: Normal Frame average = %d exceed limit [%d, %d]\n", + __func__, *mean_normal, min, max); + ret = ERROR_TEST_CHECK_FAIL; + } + + if ((percentage > 0) && ((*mean_edge < min) || (*mean_edge > max))) { + pr_err("%s: Edge Frame average = %d exceed limit [%d, %d]\n", + __func__, *mean_edge, min, max); + ret = ERROR_TEST_CHECK_FAIL; + } + + for (i = 0; i < deltas->header.force_node; i++) { + for (j = 0; j < deltas->header.sense_node; j++) { + if ((i == 0) || (i == deltas->header.force_node) || + (j == 0) || (j == deltas->header.sense_node)) + deltas->node_data[i * + deltas->header.sense_node + + j] = + deltas->node_data[i * + deltas->header. + sense_node + j] * + 100 / + (*mean_edge); + else + deltas->node_data[i * + deltas->header.sense_node + + j] = + deltas->node_data[i * + deltas->header. + sense_node + j] * + 100 / + (*mean_normal); + + if ((percentage > 0) && (deltas->node_data[i * + deltas-> + header. + sense_node + + j] > + percentage)) { + pr_err("%s: Delta Node[%d, %d] = %d exceed limit [%d]\n", + __func__, i, j, + deltas->node_data[i * + deltas + ->header.sense_node + + j], percentage); + ret = ERROR_TEST_CHECK_FAIL; + } + } + } + + + /* print average frame in the log */ + print_frame_short("FS Uniform (%) =", + array1dTo2d_short( + deltas->node_data, + deltas->node_data_size, + deltas->header.sense_node), + deltas->header.force_node, + deltas->header.sense_node); + + + if (ret < OK) + pr_err("%s: TP sensitivity MS Post Cal test FAILED... ERROR %08X\n", + __func__, ret); + else { + pr_info("%s: TP sensitivity MS Post Cal FINISHED!\n", + __func__); + ret = OK; + } + + return ret; + + +ERROR: + if (deltas->node_data != NULL) { + kfree(deltas->node_data); + deltas->node_data = NULL; + } + + + if (finalFrame->node_data != NULL) { + kfree(finalFrame->node_data); + finalFrame->node_data = NULL; + } + + return ret; +} + + +/** + * Compute Digital gains for calibration + * @param enter if =1 turn on TP Sensitivity mode, otherwise will turn it off + * @param saveGain if 1, will save the gain table into the chip otherwise will + * not save it + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_mode(u8 enter, int saveGain) +{ + int res, ret = OK; + u8 cmd[4] = { 0xC0, 0x00, 0x00, 0x00 }; + u8 sett = SPECIAL_WRITE_HOST_MEM_TO_FLASH; + + pr_info("%s: Start TP Sensitivity Mode... enter = %02X\n", + __func__, enter); + if (enter == 1) { + /* enter TP Sensitivity mode*/ + ret = fts_disableInterrupt(); + pr_info("%s: Entering TP Sensitivity Mode disabling algos...\n", + __func__); + cmd[3] = 0x01; + res = fts_writeFwCmd(cmd, 4); + if (res < OK) + pr_err("%s: Error while turning on TP Sens Mode! ERROR %08X\n", + __func__, res); + } else { + /* exit TP Sensitivity mode*/ + pr_info("%s: Exiting TP Sensitivity Mode enabling algos...\n", + __func__); + res = fts_writeFwCmd(cmd, 4); + if (res < OK) + pr_err("%s: Error while turning off TP Sens Mode! ERROR %08X\n", + __func__, res); + + if (saveGain == 1) { + pr_info("%s: Trigger writing gains into the flash...\n", + __func__); + ret = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1); + if (ret < OK) + pr_err("%s: error while writing gains into the flash! ERROR %08X\n", + __func__, res); + } + + res |= senseOn(); + res |= fts_enableInterrupt(); + } + + res |= ret; + + if (res < OK) + pr_err("%s: TP Sensitivity Mode... ERROR %08X!\n", + __func__, res); + else + pr_info("%s: TP Sensitivity Mode FINISHED!\n", __func__); + + return res; +} + + +/** + * Compute Digital gains for calibration + * @param scan select the scan mode which should be enabled + * @param enableGains =1 apply gains when computing the strength otherwise + * the gains will be ignored + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_set_scan_mode(u8 scan, int enableGains) +{ + int res, ret = OK; + u8 cmd[4] = { 0xC0, 0x00, 0x01, 0x00 }; + + + pr_info("%s: Set TP Sensitivity Scan Mode... scan = %02X, enableGains = %d\n", + __func__, scan, enableGains); + + + if (enableGains == 1) { + /* Consider Sensitivity Gains when computing Strength */ + cmd[3] = 0x01; + ret = fts_writeFwCmd(cmd, 4); + if (ret < OK) + pr_err("%s: Error while enabling Gains in TP Sens Mode! ERROR %08X\n", + __func__, ret); + } else { + /* Exclude Sensitivity Gains when computing Strength */ + ret = fts_writeFwCmd(cmd, 4); + if (ret < OK) + pr_err("%s: Error while disabling Gain in TP Sens Mode! ERROR %08X\n", + __func__, ret); + } + + res = setScanMode(SCAN_MODE_LOCKED, scan); + if (res < OK) + pr_err("Error while setting the scan frequency... ERROR %08X\n", + res); + + res |= ret; + + if (res < OK) + pr_err("%s: Set TP Sensitivity Scan Mode... ERROR %08X!\n", + __func__, res); + else + pr_info("%s: Set TP Sensitivity Scan FINISHED!\n", __func__); + + return res; +} + + + + +/** + * Compute the standard deviation for each node form a series of frames + * @param numFrames number of frames to collect to compute the standard + * deviation + * @param[out] std pointer to the frame which will contain the standard + * deviation for each node + * @return OK if success or an error code which specify the type of error + */ +int tp_sensitivity_test_std_ms(int numFrames, MutualSenseFrame *std) +{ + int ret = OK; + int i = 0, count = 0; + MutualSenseFrame frame; + int *mean = NULL;/* store the mean value for each node */ + unsigned long *stdTemp = NULL; + + + if (std == NULL) { + pr_err("%s: Invalid arguments Passed! ERROR %08X\n", + __func__, ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } + + std->node_data = NULL; + + pr_info("%s: Start TP sensitivity STD... collecting %d frames!\n", + __func__, numFrames); + + /* collect frames skipping the tests + print on the log */ + ret = getMSFrame3(MS_STRENGTH, &frame); + if (ret < OK) { + pr_err("%s: can not read MS Frame... ERROR %08X\n", + __func__, ret); + goto ERROR; + } + + std->header = frame.header; + std->node_data_size = frame.node_data_size; + + std->node_data = (short *)kzalloc(std->node_data_size * sizeof(short), + GFP_KERNEL); + mean = (int *)kzalloc(std->node_data_size * sizeof(int), GFP_KERNEL); + stdTemp = (unsigned long *)kzalloc(std->node_data_size * + sizeof(unsigned long), + GFP_KERNEL); + if (std->node_data == NULL || + mean == NULL || + stdTemp == NULL) { + pr_err("%s: can not allocate memory ERROR %08X\n", + __func__, ERROR_ALLOC | ERROR_GET_FRAME); + ret = ERROR_ALLOC | ERROR_GET_FRAME; + goto ERROR; + } + + /* collecting frames */ + do { + for (i = 0; i < frame.node_data_size; i++) { + mean[i] += frame.node_data[i]; + stdTemp[i] += frame.node_data[i] * frame.node_data[i]; + } + count++; + + if (frame.node_data != NULL) { + kfree(frame.node_data); + frame.node_data = NULL; + } + + /* exclude one more reading at the end*/ + if (count < numFrames) + ret = getMSFrame3(MS_STRENGTH, &frame); + } while ((count < numFrames) && (ret >= OK)); + + if (ret < OK) { + pr_err("%s: error while collecting the frames! ERROR%08X\n", + __func__, ret); + goto ERROR; + } + + /* compute the average for each node */ + pr_info("%s: Computing std for each node...\n", __func__); + + for (i = 0; i < std->node_data_size; i++) { + mean[i] /= numFrames; + stdTemp[i] = stdTemp[i] / numFrames - (mean[i] * mean[i]); + std->node_data[i] = (short)int_sqrt(stdTemp[i]); + } + + kfree(stdTemp); + stdTemp = NULL; + kfree(mean); + mean = NULL; + + /* print average frame in the log */ + print_frame_short("STD =", + array1dTo2d_short( + std->node_data, + std->node_data_size, + std->header.sense_node), + std->header.force_node, + std->header.sense_node); + + if (ret < OK) + pr_err("%s: TP sensitivity STD test FAILED... ERROR %08X\n", + __func__, ret); + else { + pr_info("%s: TP sensitivity STD FINISHED!\n", + __func__); + ret = OK; + } + + return ret; + +ERROR: + + kfree(frame.node_data); + frame.node_data = NULL; + + kfree(std->node_data); + std->node_data = NULL; + + kfree(stdTemp); + stdTemp = NULL; + + kfree(mean); + mean = NULL; + + return ret; +} + + +/** + * Retrieve the actual Test Limit data from the system (bin file or header + * file) + * @param path name of Production Test Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param file pointer to the LimitFile struct which will contains the limits + * data + * @return OK if success or an error code which specify the type of error + */ +int getLimitsFile(char *path, LimitFile *file) +{ + const struct firmware *fw = NULL; + struct device *dev = NULL; + int fd = -1; + + pr_info("Get Limits File starting... %s\n", path); + + if (file->data != NULL) { + /* to avoid memory leak on consecutive call of + * the function with the same pointer */ + pr_err("Pointer to Limits Data already contains something... freeing its content!\n"); + kfree(file->data); + file->data = NULL; + file->size = 0; + } + + strlcpy(file->name, path, MAX_LIMIT_FILE_NAME); + if (strncmp(path, "NULL", 4) == 0) { +#ifdef LIMITS_H_FILE + pr_info("Loading Limits File from .h!\n"); + file->size = LIMITS_SIZE_NAME; + file->data = (char *)kmalloc((file->size) * sizeof(char), + GFP_KERNEL); + if (file->data != NULL) { + memcpy(file->data, (char *)(LIMITS_ARRAY_NAME), + file->size); + return OK; + } else { + pr_err("Error while allocating data... ERROR %08X\n", + path, ERROR_ALLOC); + return ERROR_ALLOC; + } +#else + pr_err("limit file path NULL... ERROR %08X\n", + ERROR_FILE_NOT_FOUND); + return ERROR_FILE_NOT_FOUND; +#endif + } else { + dev = getDev(); + if (dev != NULL) { + pr_info("Loading Limits File from .csv!\n"); + fd = request_firmware(&fw, path, dev); + if (fd == 0) { + pr_info("Start to copy %s...\n", path); + file->size = fw->size; + file->data = (char *)kmalloc((file->size) * + sizeof(char), + GFP_KERNEL); + if (file->data != NULL) { + memcpy(file->data, (char *)fw->data, + file->size); + pr_info("Limit file Size = %d\n", + file->size); + release_firmware(fw); + return OK; + } else { + pr_err("Error while allocating data... ERROR %08X\n", + ERROR_ALLOC); + release_firmware(fw); + return ERROR_ALLOC; + } + } else { + pr_err("Request the file %s failed... ERROR %08X\n", + path, ERROR_FILE_NOT_FOUND); + return ERROR_FILE_NOT_FOUND; + } + } else { + pr_err("Error while getting the device ERROR %08X\n", + ERROR_FILE_READ); + return ERROR_FILE_READ; + } + } +} + +/** + * Reset and release the memory which store a Production Limit File previously + * loaded + * @param file pointer to the LimitFile struct to free + * @return OK if success or an error code which specify the type of error + */ + +int freeLimitsFile(LimitFile *file) +{ + pr_info("Freeing Limit File ...\n"); + if (file != NULL) { + if (file->data != NULL) { + kfree(file->data); + file->data = NULL; + } else + pr_err("Limit File was already freed!\n"); + file->size = 0; + strlcpy(file->name, " ", MAX_LIMIT_FILE_NAME); + return OK; + } else { + pr_err("Passed a NULL argument! ERROR %08X\n", + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} + +/** + * Reset and release the memory which store the current Limit File + * previously loaded + * @return OK if success or an error code which specify the type of error + */ +int freeCurrentLimitsFile(void) +{ + return freeLimitsFile(&limit_file); +} + +/** + * Parse the raw data read from a Production test limit file in order + * to find the specified information + * If no limits file data are passed, the function loads and stores the limit + * file from the system + * @param path name of Production Test Limit file to load or + * "NULL" if the limits data should be loaded by a .h file + * @param file pointer to LimitFile struct that should be parsed or + * NULL if the limit file in the system should be loaded and then parsed + * @param label string which identify a particular set of data in the file that + * want to be loaded + * @param data pointer to the pointer which will contains the specified limits + * data + * as 1 dimension matrix with data arranged row after row + * @param row pointer to a int variable which will contain the number of row of + * data + * @param column pointer to a int variable which will contain the number of + * column of data + * @return OK if success or an error code which specify the type of error + */ +int parseProductionTestLimits(char *path, LimitFile *file, char *label, + int **data, int *row, int *column) +{ + int find = 0; + char *token = NULL; + int i = 0; + int j = 0; + int z = 0; + + char *line2 = NULL; + char line[800]; + char *buf = NULL; + int n, size, pointer = 0, ret = OK; + char *data_file = NULL; + + if (file == NULL || strcmp(path, file->name) != 0 || file->size == 0) { + pr_info("No limit File data passed... try to get them from the system!\n"); + ret = getLimitsFile(LIMITS_FILE, &limit_file); + if (ret < OK) { + pr_err("parseProductionTestLimits: ERROR %08X\n", + ERROR_FILE_NOT_FOUND); + return ERROR_FILE_NOT_FOUND; + } + size = limit_file.size; + data_file = limit_file.data; + } else { + pr_info("Limit File data passed as arguments!\n"); + size = file->size; + data_file = file->data; + } + + + + pr_info("The size of the limits file is %d bytes...\n", size); + + + + while (find == 0) { + /* start to look for the wanted label */ + if (readLine(&data_file[pointer], line, size - pointer, &n) < + 0) { + find = -1; + break; + } + pointer += n; + if (line[0] == '*') { + /* each header row start with * ex. *label,n_row,n_colum */ + line2 = kstrdup(line, GFP_KERNEL); + if (line2 == NULL) { + pr_err("parseProductionTestLimits: kstrdup ERROR %08X\n", + ERROR_ALLOC); + ret = ERROR_ALLOC; + goto END; + } + buf = line2; + line2 += 1; + token = strsep(&line2, ","); + if (strcmp(token, label) == 0) { + /* if the row is the wanted one, r + * retrieve rows and columns info */ + find = 1; + token = strsep(&line2, ","); + if (token != NULL) { + sscanf(token, "%d", row); + pr_info("Row = %d\n", *row); + } else { + pr_err("parseProductionTestLimits 1: ERROR %08X\n", + ERROR_FILE_PARSE); + ret = ERROR_FILE_PARSE; + goto END; + } + token = strsep(&line2, ","); + if (token != NULL) { + sscanf(token, "%d", column); + pr_info("Column = %d\n", *column); + } else { + pr_err("parseProductionTestLimits 2: ERROR %08X\n", + ERROR_FILE_PARSE); + ret = ERROR_FILE_PARSE; + goto END; + } + + kfree(buf); + buf = NULL; + *data = (int *)kmalloc(((*row) * (*column)) * + sizeof(int), GFP_KERNEL); + /* allocate the memory for containing the data */ + j = 0; + if (*data == NULL) { + pr_err("parseProductionTestLimits: ERROR %08X\n", + ERROR_ALLOC); + ret = ERROR_ALLOC; + goto END; + } + + + /* start to read the data */ + for (i = 0; i < *row; i++) { + if (readLine(&data_file[pointer], line, + size - pointer, &n) < 0) { + pr_err("parseProductionTestLimits : ERROR %08X\n", + ERROR_FILE_READ); + ret = ERROR_FILE_READ; + goto END; + } + pointer += n; + line2 = kstrdup(line, GFP_KERNEL); + if (line2 == NULL) { + pr_err("parseProductionTestLimits: kstrdup ERROR %08X\n", + ERROR_ALLOC); + ret = ERROR_ALLOC; + goto END; + } + buf = line2; + token = strsep(&line2, ","); + for (z = 0; (z < *column) && (token != + NULL); + z++) { + sscanf(token, "%d", ((*data) + + j)); + j++; + token = strsep(&line2, ","); + } + kfree(buf); + buf = NULL; + } + if (j == ((*row) * (*column))) { + /* check that all the data are read */ + pr_info("READ DONE!\n"); + ret = OK; + goto END; + } + pr_err("parseProductionTestLimits 3: ERROR %08X\n", + ERROR_FILE_PARSE); + ret = ERROR_FILE_PARSE; + goto END; + } + kfree(buf); + buf = NULL; + } + } + pr_err("parseProductionTestLimits: ERROR %08X\n", + ERROR_LABEL_NOT_FOUND); + ret = ERROR_LABEL_NOT_FOUND; +END: + if (buf != NULL) + kfree(buf); + return ret; +} + + +/** + * Read one line of a text file passed as array of byte and terminate it with + * a termination character '\0' + * @param data text file as array of bytes + * @param line pointer to an array of char that will contain the line read + * @param size size of data + * @param n pointer to a int variable which will contain the number of + * characters of the line + * @return OK if success or an error code which specify the type of error + */ +int readLine(char *data, char *line, int size, int *n) +{ + int i = 0; + + if (size < 1) + return ERROR_OP_NOT_ALLOW; + + while (data[i] != '\n' && i < size) { + line[i] = data[i]; + i++; + } + *n = i + 1; + line[i] = '\0'; + + return OK; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTest.h b/drivers/input/touchscreen/stm/fts_lib/ftsTest.h new file mode 100644 index 000000000000..7554709cdd12 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTest.h @@ -0,0 +1,343 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS API for MP test ** + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTest.h + * \brief Contains all the definitions and structs related to the Mass + *Production Test + */ + +#ifndef FTS_TEST_H +#define FTS_TEST_H + +#include "ftsSoftware.h" +#include "ftsFrame.h" + +#ifndef LIMITS_H_FILE +/* /< Name of the Production Test Limit File */ +#define LIMITS_FILE "stm_fts_production_limits.csv" +#else +#define LIMITS_FILE "NULL" +#endif + +#define WAIT_FOR_FRESH_FRAMES 200 /* /< Time in ms to wait after + * start to sensing before + * reading a frame */ +#define WAIT_AFTER_SENSEOFF 50 /* /< Time in ms to wait after + * stop sensing and before + * reading a frame from + * memory */ + +#define NO_INIT 0 /* /< No Initialization required + * during the MP */ + +#define RETRY_INIT_BOOT 3 /* /< number of retry of the + * init process at boot */ + +#define SENS_TEST_NUM_FRAMES 100 /* /< number of frames to read */ +#define SENS_TEST_PERC_TARGET_PRECAL 20 /* /< +-% of target value within + * all the node of the frames + * should be contained */ +#define SENS_TEST_PERC_TARGET_POSTCAL 4 /* /< +-% of target value within + * should be contained the + * avarege of the nodes and the + * deltas for each node */ + +/** @defgroup mp_test Mass Production Test + * Mass production test API. + * Mass Production Test (MP) should be executed at least one time in the life + * of every device \n + * It used to verify that tit is not present any hardware damage and + * initialize some value of the chip in order to guarantee the working + * performance \n + * The MP test is made up by 3 steps: + * - ITO test = production_test_ito() \n + * - Initialization = production_test_initialization() \n + * - Data Test = production_test_data(), + * it is possible to select which items test thanks to the TestToDo struct\n + * To execute the Data Test it is mandatory load some thresholds that + * are stored in the Limit File. + * @{ + */ + +/** @defgroup limit_file Limit File + * @ingroup mp_test + * Production Test Limit File is a csv which contains thresholds of the data to + * test. + * This file can be loaded from the file system or stored as a header file + * according to the LIMITS_H_FILE define \n + * For each selectable test item there can be one or more associated labels + * which store the corresponding thresholds \n + * @{ + */ +/* LABELS PRODUCTION TEST LIMITS FILE */ +/** @defgroup test_labels Test Items Labels + * @ingroup limit_file + * Labels present in the Limit File and associated to the test items of + * TestToDo + * @{ + */ +#define MS_RAW_MIN_MAX "MS_RAW_DATA_MIN_MAX" +#define MS_RAW_GAP "MS_RAW_DATA_GAP" +#define MS_RAW_ADJH "MS_RAW_DATA_ADJ_HORIZONTAL" +#define MS_RAW_ADJV "MS_RAW_DATA_ADJ_VERTICAL" +#define MS_RAW_ITO_ADJH "MS_RAW_ITO_DATA_ADJ_HORIZONTAL" +#define MS_RAW_ITO_ADJV "MS_RAW_ITO_DATA_ADJ_VERTICAL" +#define MS_RAW_LP_MIN_MAX "MS_RAW_LOWPOWER_DATA_MIN_MAX" +#define MS_RAW_LP_GAP "MS_RAW_LOWPOWER_DATA_GAP" +#define MS_RAW_LP_ADJH "MS_RAW_LOWPOWER_DATA_ADJ_HORIZONTAL" +#define MS_RAW_LP_ADJV "MS_RAW_LOWPOWER_DATA_ADJ_VERTICAL" +#define MS_CX1_MIN_MAX "MS_TOUCH_ACTIVE_CX1_MIN_MAX" +#define MS_CX2_MAP_MIN "MS_TOUCH_ACTIVE_CX2_MIN" +#define MS_CX2_MAP_MAX "MS_TOUCH_ACTIVE_CX2_MAX" +#define MS_CX2_ADJH_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL" +#define MS_CX2_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL" +#define MS_TOTAL_CX_MAP_MIN "MS_TOUCH_ACTIVE_TOTAL_CX_MIN" +#define MS_TOTAL_CX_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_MAX" +#define MS_TOTAL_CX_ADJH_MAP_MAX \ + "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL" +#define MS_TOTAL_CX_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL" +#define SS_RAW_FORCE_MIN_MAX "SS_RAW_DATA_FORCE_MIN_MAX" +#define SS_RAW_SENSE_MIN_MAX "SS_RAW_DATA_SENSE_MIN_MAX" +#define SS_RAW_FORCE_GAP "SS_RAW_DATA_FORCE_GAP" +#define SS_RAW_SENSE_GAP "SS_RAW_DATA_SENSE_GAP" +#define SS_RAW_LP_FORCE_MIN_MAX "SS_RAW_LOWPOWER_DATA_FORCE_MIN_MAX" +#define SS_RAW_LP_SENSE_MIN_MAX "SS_RAW_LOWPOWER_DATA_SENSE_MIN_MAX" +#define SS_RAW_LP_FORCE_GAP "SS_RAW_LOWPOWER_DATA_FORCE_GAP" +#define SS_RAW_LP_SENSE_GAP "SS_RAW_LOWPOWER_DATA_SENSE_GAP" +#define SS_IX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_FORCE_MIN_MAX" +#define SS_IX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_SENSE_MIN_MAX" +#define SS_CX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_FORCE_MIN_MAX" +#define SS_CX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_SENSE_MIN_MAX" +#define SS_IX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_FORCE_MIN" +#define SS_IX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_FORCE_MAX" +#define SS_IX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_SENSE_MIN" +#define SS_IX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_SENSE_MAX" +#define SS_IX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_VERTICAL" +#define SS_IX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_HORIZONTAL" +#define SS_CX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_FORCE_MIN" +#define SS_CX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_FORCE_MAX" +#define SS_CX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_SENSE_MIN" +#define SS_CX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_SENSE_MAX" +#define SS_CX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL" +#define SS_CX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL" + +/* TOTAL SS */ +#define SS_TOTAL_IX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MIN" +#define SS_TOTAL_IX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MAX" +#define SS_TOTAL_IX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MIN" +#define SS_TOTAL_IX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MAX" +#define SS_TOTAL_IX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_VERTICAL" +#define SS_TOTAL_IX_SENSE_ADJH_MAP_MAX \ + "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_HORIZONTAL" +#define SS_TOTAL_CX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MIN" +#define SS_TOTAL_CX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MAX" +#define SS_TOTAL_CX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MIN" +#define SS_TOTAL_CX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MAX" +#define SS_TOTAL_CX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL" +#define SS_TOTAL_CX_SENSE_ADJH_MAP_MAX \ + "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL" + +/* KEYS */ +#define MS_KEY_RAW_MIN_MAX "MS_KEY_RAW_DATA_MIN_MAX" +#define MS_KEY_CX1_MIN_MAX "MS_KEY_CX1_MIN_MAX" +#define MS_KEY_CX2_MAP_MIN "MS_KEY_CX2_MIN" +#define MS_KEY_CX2_MAP_MAX "MS_KEY_CX2_MAX" +#define MS_KEY_TOTAL_CX_MAP_MIN "MS_KEY_TOTAL_CX_MIN" +#define MS_KEY_TOTAL_CX_MAP_MAX "MS_KEY_TOTAL_CX_MAX" + +/* CONSTANT TOTAL IX */ +#define SS_IX1_FORCE_W "IX1_FORCE_W" +#define SS_IX2_FORCE_W "IX2_FORCE_W" +#define SS_IX1_SENSE_W "IX1_SENSE_W" +#define SS_IX2_SENSE_W "IX2_SENSE_W" +/** @}*/ + + +/** + * Struct used to specify which test perform during the Mass Production Test. + * For each test item selected in this structure, there should be one or + * more labels associated in the Limit file from where load the thresholds + */ +typedef struct { + int MutualRaw; /* /< MS Raw min/Max test */ + int MutualRawGap; /* /< MS Raw Gap(max-min) test */ + int MutualRawAdj; /* /< MS Raw Adjacent test */ + int MutualRawLP; /* /< MS Low Power Raw min/Max test */ + int MutualRawGapLP; /* /< MS Low Power Raw Gap(max-min) test */ + int MutualRawAdjLP; /* /< MS Low Power Raw Adjacent test */ + int MutualRawAdjITO; /* /< MS Raw Adjacent test during ITO test */ + + int MutualCx1; /* /< MS Cx1 min/Max test */ + int MutualCx2; /* /< MS Cx2 min/Max (for each node) test */ + int MutualCx2Adj; /* /< MS Vertical and Horizontal Adj Cx2 min/Max + * (for each node) test */ + int MutualCxTotal; /* /< MS Total Cx min/Max (for each node) test + * */ + int MutualCxTotalAdj; /* /< MS Total vertical and Horizontal Adj Cx2 + * min/Max + * (for each node) test */ + + int MutualKeyRaw; /* /< MS Raw Key min/Max test */ + int MutualKeyCx1; /* /< MS Cx1 Key min/Max test */ + int MutualKeyCx2; /* /< MS Cx2 Key min/Max (for each node) test */ + int MutualKeyCxTotal; /* /< MS Total Cx Key min/Max (for each node) + * test */ + + int SelfForceRaw; /* /< SS Force Raw min/Max test */ + int SelfForceRawGap; /* /< SS Force Raw Gap(max-min) test */ + int SelfForceRawLP; /* /< SS Low Power Force Raw min/Max test */ + int SelfForceRawGapLP; /* /< SS Low Power Force Raw Gap(max-min) test */ + + int SelfForceIx1; /* /< SS Force Ix1 min/Max test */ + int SelfForceIx2; /* /< SS Force Ix2 min/Max (for each node) test + * */ + int SelfForceIx2Adj; /* /< SS Vertical Adj Force Ix2 min/Max + * (for each node) test */ + int SelfForceIxTotal; /* /< SS Total Force Ix min/Max (for each node) + * test */ + int SelfForceIxTotalAdj; /* /< SS Total Vertical Adj Force Ix + * min/Max + * (for each node) test */ + int SelfForceCx1; /* /< SS Force Cx1 min/Max test */ + int SelfForceCx2; /* /< SS Force Cx2 min/Max (for each node) test */ + int SelfForceCx2Adj; /* /< SS Vertical Adj Force Cx2 min/Max (for + * each node) test */ + int SelfForceCxTotal; /* /< SS Total Force Cx min/Max (for each node) + * test */ + int SelfForceCxTotalAdj; /* /< SS Total Vertical Adj Force Cx + * min/Max + * (for each node) test */ + + int SelfSenseRaw; /* /< SS Sense Raw min/Max test */ + int SelfSenseRawGap; /* /< SS Sense Raw Gap(max-min) test */ + int SelfSenseRawLP; /* /< SS Low Power Sense Raw min/Max test */ + int SelfSenseRawGapLP; /* /< SS Low Power Sense Raw Gap(max-min) test */ + + int SelfSenseIx1; /* /< SS Sense Ix1 min/Max test */ + int SelfSenseIx2; /* /< SS Sense Ix2 min/Max (for each node) test */ + int SelfSenseIx2Adj; /* /< SS Horizontal Adj Sense Ix2 min/Max + * (for each node) test */ + int SelfSenseIxTotal; /* /< SS Total Horizontal Sense Ix min/Max + * (for each node) test */ + int SelfSenseIxTotalAdj; /* /< SS Total Horizontal Adj Sense Ix + * min/Max + * (for each node) test */ + int SelfSenseCx1; /* /< SS Sense Cx1 min/Max test */ + int SelfSenseCx2; /* /< SS Sense Cx2 min/Max (for each node) test */ + int SelfSenseCx2Adj; /* /< SS Horizontal Adj Sense Cx2 min/Max + * (for each node) test */ + int SelfSenseCxTotal; /* /< SS Total Sense Cx min/Max (for each node) + * test */ + int SelfSenseCxTotalAdj; /* /< SS Total Horizontal Adj Sense Cx + * min/Max + * (for each node) test */ +} TestToDo; + + +#define MAX_LIMIT_FILE_NAME 100 /* /< max number of chars of the limit file name + * */ + +/** + * Struct which store the data coming from a Production Limit File + */ +typedef struct { + char *data; /* /< pointer to an array of char which contains + * the content of the Production Limit File */ + int size; /* /< size of data */ + char name[MAX_LIMIT_FILE_NAME]; /* /< identifier of the source from + * where the limits data were loaded + * (if loaded from a file it will be + * the file name, while if loaded + * from .h will be "NULL") */ +} LimitFile; + + + +int initTestToDo(void); +/**@}*/ + +/**@}*/ + + +int computeAdjHoriz(i8 *data, int row, int column, u8 **result); +int computeAdjHorizTotal(short *data, int row, int column, u16 **result); +int computeAdjVert(i8 *data, int row, int column, u8 **result); +int computeAdjVertTotal(short *data, int row, int column, u16 **result); +int computeAdjHorizFromU(u8 *data, int row, int column, u8 **result); +int computeAdjHorizTotalFromU(u16 *data, int row, int column, u16 **result); +int computeAdjVertFromU(u8 *data, int row, int column, u8 **result); +int computeAdjVertTotalFromU(u16 *data, int row, int column, u16 **result); +int checkLimitsMinMax(short *data, int row, int column, int min, int max); +int checkLimitsMap(i8 *data, int row, int column, int *min, int *max); +int checkLimitsMapTotal(short *data, int row, int column, int *min, int *max); +int checkLimitsMapFromU(u8 *data, int row, int column, int *min, int *max); +int checkLimitsMapTotalFromU(u16 *data, int row, int column, int *min, + int *max); +int checkLimitsMapAdj(u8 *data, int row, int column, int *max); +int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max); + +/** @defgroup mp_api MP API + * @ingroup mp_test + * Functions to execute the MP test. + * The parameters of these functions allow to customize their behavior + * in order to satisfy different scenarios + * @{ + */ +int production_test_ito(char *path_limits, TestToDo *todo); +int production_test_initialization(u8 type); +int production_test_main(char *pathThresholds, int stop_on_fail, int saveInit, + TestToDo *todo); +int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo); +int production_test_ms_raw_lp(char *path_limits, int stop_on_fail, + TestToDo *todo); +int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo); +int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo); +int production_test_ss_raw_lp(char *path_limits, int stop_on_fail, + TestToDo *todo); +int production_test_ss_ix_cx(char *path_limits, int stop_on_fail, + TestToDo *todo); +int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo); +int production_test_ms_key_cx(char *path_limits, int stop_on_fail, + TestToDo *todo); +int production_test_ms_key_raw(char *path_limits); +/** @}*/ + +/** + * @addtogroup limit_file + * @{ + */ +int parseProductionTestLimits(char *path, LimitFile *file, char *label, + int **data, int *row, int *column); +int readLine(char *data, char *line, int size, int *n); +int getLimitsFile(char *path, LimitFile *file); +int freeLimitsFile(LimitFile *file); +int freeCurrentLimitsFile(void); +/**@}*/ + +int tp_sensitivity_test_pre_cal_ms(MutualSenseFrame *finalFrame, short target, + int percentage); +int tp_sensitivity_test_pre_cal_ss(SelfSenseFrame *finalFrame, short target, + int percentage); +int tp_sensitivity_compute_gains(MutualSenseFrame *frame, short target, + int saveGain); +int tp_sensitivity_test_post_cal_ms(MutualSenseFrame *finalFrame, + MutualSenseFrame *deltas, short target, + int percentage, int *mean_normal, + int *mean_edge); +int tp_sensitivity_set_scan_mode(u8 scan, int enableGains); +int tp_sensitivity_mode(u8 enter, int saveGain); +int tp_sensitivity_test_std_ms(int numFrames, MutualSenseFrame *std); +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTime.c b/drivers/input/touchscreen/stm/fts_lib/ftsTime.c new file mode 100644 index 000000000000..a8b5f880bc20 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTime.c @@ -0,0 +1,84 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Utility for mesuring/handling the time * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTime.c + * \brief Contains all functions to handle and measure the time in the driver + */ + +#include "ftsTime.h" + + +#include <linux/errno.h> + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/time.h> +#include <linux/delay.h> +#include <linux/ctype.h> + + +/** + * Take the starting time and save it in a StopWatch variable + * @param w pointer of a StopWatch struct + */ +void startStopWatch(StopWatch *w) +{ + ktime_get_coarse_real_ts64(&w->start); +} + +/** + * Take the stop time and save it in a StopWatch variable + * @param w pointer of a StopWatch struct + */ +void stopStopWatch(StopWatch *w) +{ + ktime_get_coarse_real_ts64(&w->end); +} + +/** + * Compute the amount of time spent from when the startStopWatch and then + * the stopStopWatch were called on the StopWatch variable + * @param w pointer of a StopWatch struct + * @return amount of time in ms (the return value is meaningless + * if the startStopWatch and stopStopWatch were not called before) + */ +int elapsedMillisecond(StopWatch *w) +{ + int result; + + result = ((w->end.tv_sec - w->start.tv_sec) * 1000) + + (w->end.tv_nsec - w->start.tv_nsec) / 1000000; + return result; +} + +/** + * Compute the amount of time spent from when the startStopWatch and + * then the stopStopWatch were called on the StopWatch variable + * @param w pointer of a StopWatch struct + * @return amount of time in ns (the return value is meaningless + * if the startStopWatch and stopStopWatch were not called before) + */ +int elapsedNanosecond(StopWatch *w) +{ + int result; + + result = ((w->end.tv_sec - w->start.tv_sec) * 1000000000) + + (w->end.tv_nsec - w->start.tv_nsec); + return result; +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTime.h b/drivers/input/touchscreen/stm/fts_lib/ftsTime.h new file mode 100644 index 000000000000..b38b188d957c --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTime.h @@ -0,0 +1,70 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Utility for measuring/handling the time * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTime.h + * \brief Contains all the definitions and structs to handle and measure the + * time in the driver + */ + +#ifndef FTS_TIME_H +#define FTS_TIME_H + + +#include <linux/time.h> + +/* TIMEOUT */ +/** @defgroup timeouts Timeouts + * Definitions of all the Timeout used in several operations + * @{ + */ +#define TIMEOUT_RESOLUTION 2 +/* /< timeout resolution in ms (all timeout should be multiples of this unit) */ +#define GENERAL_TIMEOUT (50 * TIMEOUT_RESOLUTION) +/* /< general timeout in ms */ +#define RELEASE_INFO_TIMEOUT (15 * TIMEOUT_RESOLUTION) +/* /< timeout to request release info in ms */ + + +#define TIMEOUT_REQU_COMP_DATA (100 * TIMEOUT_RESOLUTION) +/* /< timeout to request compensation data in ms */ +#define TIMEOUT_REQU_DATA (200 * TIMEOUT_RESOLUTION) +/* /< timeout to request data in ms */ +#define TIMEOUT_ITO_TEST_RESULT (100 * TIMEOUT_RESOLUTION) +/* /< timeout to perform ito test in ms */ +#define TIMEOUT_INITIALIZATION_TEST_RESULT (5000 * TIMEOUT_RESOLUTION) +/* /< timeout to perform initialization test in ms */ +#define TIEMOUT_ECHO \ + TIMEOUT_INITIALIZATION_TEST_RESULT +/* /< timeout of the echo command, should be the max of + * all the possible commands (used in worst case) */ +/** @}*/ + + +/** + * Struct used to measure the time elapsed between a starting and ending point. + */ +typedef struct { + struct timespec64 start; /* /< store the starting time */ + struct timespec64 end; /* /< store the finishing time */ +} StopWatch; + + +void startStopWatch(StopWatch *w); +void stopStopWatch(StopWatch *w); +int elapsedMillisecond(StopWatch *w); +int elapsedNanosecond(StopWatch *w); + +#endif diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTool.c b/drivers/input/touchscreen/stm/fts_lib/ftsTool.c new file mode 100644 index 000000000000..5d34dfb78d89 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTool.c @@ -0,0 +1,730 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Utility Functions * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTool.c + * \brief Contains all the functions to support common operation inside the + * driver + */ + +#include "ftsCompensation.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsHardware.h" +#include "ftsIO.h" +#include "ftsSoftware.h" +#include "ftsTime.h" +#include "ftsTool.h" +#include "../fts.h" /* needed for the tag define */ + + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <stdarg.h> +#include <linux/serio.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/ctype.h> + + +/** + * Print an array of byte in a HEX string and attach at the beginning a label. + * The function allocate memory that should be free outside the function itself + * @param label string to attach at the beginning + * @param buff pointer to the byte array that should be printed as HEX string + * @param count size of buff + * @param result pointer to the array of characters that compose the HEX final + * string + * @param size size of result + * @return pointer to the array of characters that compose the HEX string, + * (same address of result) + * @warning result MUST be allocated outside the function and should be + * big enough to contain the data converted as HEX! + */ +char *printHex(char *label, u8 *buff, int count, u8 *result, int size) +{ + int i, offset = 0; + + offset = scnprintf(result + offset, size - offset, "%s", label); + for (i = 0; i < count; i++) { + offset += + scnprintf(result + offset, + size - offset, "%02X ", buff[i]); + /* this append automatically a null terminator char */ + } + return result; +} + +/** + * Clear the FIFO from any event + * @return OK if success or an error code which specify the type of error + */ +int flushFIFO(void) +{ + int ret; + u8 sett = SPECIAL_FIFO_FLUSH; + + ret = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1); /* flush the FIFO */ + if (ret < OK) { + pr_err("flushFIFO: ERROR %08X\n", ret); + return ret; + } + + pr_info("FIFO flushed!\n"); + return OK; +} + + + +/** + * Convert an array of bytes to an array of u16 taking two bytes at time, + * src has LSB first. + * @param src pointer to the source byte array + * @param src_length size of src + * @param dst pointer to the destination array. + * @return the final size of dst (half of the source) or ERROR_OP_NOT_ALLOW + * if the size of src is not multiple of 2. + */ +int u8ToU16n(u8 *src, int src_length, u16 *dst) +{ + int i, j; + + if (src_length % 2 != 0) + return ERROR_OP_NOT_ALLOW; + else { + j = 0; + dst = (u16 *)kmalloc((src_length / 2) * sizeof(u16), + GFP_KERNEL); + for (i = 0; i < src_length; i += 2) { + dst[j] = ((src[i + 1] & 0x00FF) << 8) + + (src[i] & 0x00FF); + j++; + } + } + + return src_length / 2; +} + +/** + * Convert an array of 2 bytes to a u16, src has LSB first (little endian). + * @param src pointer to the source byte array + * @param dst pointer to the destination u16. + * @return OK + */ +int u8ToU16(u8 *src, u16 *dst) +{ + *dst = (u16)(((src[1] & 0x00FF) << 8) + (src[0] & 0x00FF)); + return OK; +} + +/** + * Convert an array of 2 bytes to a u16, src has MSB first (big endian). + * @param src pointer to the source byte array + * @param dst pointer to the destination u16. + * @return OK + */ +int u8ToU16_be(u8 *src, u16 *dst) +{ + *dst = (u16)(((src[0] & 0x00FF) << 8) + (src[1] & 0x00FF)); + return OK; +} + +/** + * Convert an array of u16 to an array of u8, dst has MSB first (big endian). + * @param src pointer to the source array of u16 + * @param src_length size of src + * @param dst pointer to the destination array of u8. This array should be free + * when no need anymore + * @return size of dst (src size multiply by 2) + */ +int u16ToU8n_be(u16 *src, int src_length, u8 *dst) +{ + int i, j; + + dst = (u8 *)kmalloc((2 * src_length) * sizeof(u8), GFP_KERNEL); + j = 0; + for (i = 0; i < src_length; i++) { + dst[j] = (u8)(src[i] & 0xFF00) >> 8; + dst[j + 1] = (u8)(src[i] & 0x00FF); + j += 2; + } + + return src_length * 2; +} + +/** + * Convert a u16 to an array of 2 u8, dst has MSB first (big endian). + * @param src u16 to convert + * @param dst pointer to the destination array of 2 u8. + * @return OK + */ +int u16ToU8_be(u16 src, u8 *dst) +{ + dst[0] = (u8)((src & 0xFF00) >> 8); + dst[1] = (u8)(src & 0x00FF); + return OK; +} + + +/** + * Convert a u16 to an array of 2 u8, dst has LSB first (little endian). + * @param src u16 to convert + * @param dst pointer to the destination array of 2 u8. + * @return OK + */ +int u16ToU8(u16 src, u8 *dst) +{ + dst[1] = (u8)((src & 0xFF00) >> 8); + dst[0] = (u8)(src & 0x00FF); + return OK; +} + +/** + * Convert an array of bytes to a u32, src has LSB first (little endian). + * @param src array of bytes to convert + * @param dst pointer to the destination u32 variable. + * @return OK + */ +int u8ToU32(u8 *src, u32 *dst) +{ + *dst = (u32)(((src[3] & 0xFF) << 24) + ((src[2] & 0xFF) << 16) + + ((src[1] & 0xFF) << 8) + (src[0] & 0xFF)); + return OK; +} + +/** + * Convert an array of bytes to a u32, src has MSB first (big endian). + * @param src array of bytes to convert + * @param dst pointer to the destination u32 variable. + * @return OK + */ +int u8ToU32_be(u8 *src, u32 *dst) +{ + *dst = (u32)(((src[0] & 0xFF) << 24) + ((src[1] & 0xFF) << 16) + + ((src[2] & 0xFF) << 8) + (src[3] & 0xFF)); + return OK; +} + + +/** + * Convert a u32 to an array of 4 bytes, dst has LSB first (little endian). + * @param src u32 value to convert + * @param dst pointer to the destination array of 4 bytes. + * @return OK + */ +int u32ToU8(u32 src, u8 *dst) +{ + dst[3] = (u8)((src & 0xFF000000) >> 24); + dst[2] = (u8)((src & 0x00FF0000) >> 16); + dst[1] = (u8)((src & 0x0000FF00) >> 8); + dst[0] = (u8)(src & 0x000000FF); + return OK; +} + +/** + * Convert a u32 to an array of 4 bytes, dst has MSB first (big endian). + * @param src u32 value to convert + * @param dst pointer to the destination array of 4 bytes. + * @return OK + */ +int u32ToU8_be(u32 src, u8 *dst) +{ + dst[0] = (u8)((src & 0xFF000000) >> 24); + dst[1] = (u8)((src & 0x00FF0000) >> 16); + dst[2] = (u8)((src & 0x0000FF00) >> 8); + dst[3] = (u8)(src & 0x000000FF); + return OK; +} + +/** + * Execute a function passed as argment and retry it defined number of times if + * not successful + * @param code pointer to a function which return an int and doesn't have any + * parameters + * @param wait_before_retry interval of time in ms to wait between one trial + * and another one + * @param retry_count max number of retry to attemp + * @return last return value obtained from the last execution of the code + *function + */ +int attempt_function(int (*code)(void), unsigned long wait_before_retry, int + retry_count) +{ + int result; + int count = 0; + + do { + result = code(); + count++; + mdelay(wait_before_retry); + } while (count < retry_count && result < 0); + + + if (count == retry_count) + return result | ERROR_TIMEOUT; + else + return result; +} + +/** + * Enable all the possible sensing mode supported by the FW + * @return OK if success or an error code which specify the type of error + */ +int senseOn(void) +{ + int ret; + + ret = setScanMode(SCAN_MODE_ACTIVE, 0xFF); /* enable all */ + if (ret < OK) { + pr_err("senseOn: ERROR %08X\n", ret); + return ret; + } + + pr_info("senseOn: SENSE ON\n"); + return OK; +} + +/** + * Disable all the sensing mode + * @return OK if success or an error code which specify the type of error + */ +int senseOff(void) +{ + int ret; + + ret = setScanMode(SCAN_MODE_ACTIVE, 0x00); + if (ret < OK) { + pr_err("senseOff: ERROR %08X\n", ret); + return ret; + } + + pr_info("senseOff: SENSE OFF\n"); + return OK; +} + + + +/** + * Clean up the IC status executing a system reset and giving + * the possibility to re-enabling the sensing + * @param enableTouch if 1, re-enable the sensing and the interrupt of the IC + * @return OK if success or an error code which specify the type of error + */ +int cleanUp(int enableTouch) +{ + int res; + + pr_info("cleanUp: system reset...\n"); + res = fts_system_reset(); + if (res < OK) + return res; + if (enableTouch) { + pr_info("cleanUp: enabling touches...\n"); + res = senseOn(); /* already enable everything */ + if (res < OK) + return res; + pr_info("cleanUp: enabling interrupts...\n"); + res = fts_enableInterrupt(); + if (res < OK) + return res; + } + return OK; +} + +/** + * Transform an array of short in a matrix of short with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of short where for each row there are + * columns elements + */ +short **array1dTo2d_short(short *data, int size, int columns) +{ + int i; + short **matrix = (short **)kmalloc(((int)(size / columns)) * + sizeof(short *), GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) + matrix[i] = (short *)kmalloc(columns * sizeof(short), + GFP_KERNEL); + + for (i = 0; i < size; i++) + matrix[i / columns][i % columns] = data[i]; + } + + return matrix; +} + +/** + * Transform an array of u16 in a matrix of u16 with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of u16 where for each row there are columns + * elements + */ +u16 **array1dTo2d_u16(u16 *data, int size, int columns) +{ + int i; + u16 **matrix = (u16 **)kmalloc(((int)(size / columns)) * sizeof(u16 *), + GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) + matrix[i] = (u16 *)kmalloc(columns * sizeof(u16), + GFP_KERNEL); + + for (i = 0; i < size; i++) + matrix[i / columns][i % columns] = data[i]; + } + + return matrix; +} + +/** + * Transform an array of u8 in a matrix of u8 with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of short where for each row there are + * columns elements + */ +u8 **array1dTo2d_u8(u8 *data, int size, int columns) +{ + int i; + u8 **matrix = (u8 **)kmalloc(((int)(size / columns)) * sizeof(u8 *), + GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) + matrix[i] = (u8 *)kmalloc(columns * sizeof(u8), + GFP_KERNEL); + + for (i = 0; i < size; i++) + matrix[i / columns][i % columns] = data[i]; + } + + return matrix; +} + +/** + * Transform an array of i8 in a matrix of i8 with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of short where for each row there are + * columns elements + */ +i8 **array1dTo2d_i8(i8 *data, int size, int columns) +{ + int i; + i8 **matrix = (i8 **)kmalloc(((int)(size / columns)) * sizeof(i8 *), + GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) + matrix[i] = (i8 *)kmalloc(columns * sizeof(i8), + GFP_KERNEL); + + for (i = 0; i < size; i++) + matrix[i / columns][i % columns] = data[i]; + } + + return matrix; +} + +/** + * Print in the kernel log a label followed by a matrix of short row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of short which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_short(char *label, short **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + buff_len = (6 + 1) * column + 1; /* -32768 str len: 6 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + pr_info("%s\n", label); + for (i = 0; i < row; i++) { + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of u16 row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u16 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_u16(char *label, u16 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + buff_len = (5 + 1) * column + 1; /* 65535 str len: 5 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + pr_info("%s\n", label); + for (i = 0; i < row; i++) { + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of u8 row x columns and + * free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u8 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_u8(char *label, u8 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + buff_len = (3 + 1) * column + 1; /* 255 str len: 3 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + pr_info("%s\n", label); + for (i = 0; i < row; i++) { + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of i8 row x columns and + * free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u8 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_i8(char *label, i8 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + buff_len = (4 + 1) * column + 1; /* -128 str len: 4 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + pr_info("%s\n", label); + for (i = 0; i < row; i++) { + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of u32 row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u32 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_u32(char *label, u32 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + buff_len = (10 + 1) * column + 1; /* 4294967295 str len: 10 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + pr_info("%s\n", label); + for (i = 0; i < row; i++) { + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of int row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of int which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_int(char *label, int **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + buff_len = (11 + 1) * column + 1; /* -2147483648 str len: 11 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + pr_info("%s\n", label); + for (i = 0; i < row; i++) { + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + + +/** + * Convert an array of bytes to an u64, src has MSB first (big endian). + * @param src array of bytes + * @param dest pointer to the destination u64. + * @param size size of src (can be <= 8) + * @return OK if success or ERROR_OP_NOT_ALLOW if size exceed 8 + */ +int u8ToU64_be(u8 *src, u64 *dest, int size) +{ + int i = 0; + + /* u64 temp =0; */ + if (size > sizeof(u64)) + return ERROR_OP_NOT_ALLOW; + + *dest = 0; + for (i = 0; i < size; i++) + *dest |= (u64)(src[i]) << ((size - 1 - i) * 8); + + return OK; +} + +/** + * Convert an u64 to an array of bytes, dest has MSB first (big endian). + * @param src value of u64 + * @param dest pointer to the destination array of bytes. + * @param size size of src (can be <= 8) + * @return OK if success or ERROR_OP_NOT_ALLOW if size exceed 8 + */ +int u64ToU8_be(u64 src, u8 *dest, int size) +{ + int i = 0; + + if (size > sizeof(u64)) + return ERROR_OP_NOT_ALLOW; + else + for (i = 0; i < size; i++) + dest[i] = (u8)((src >> ((size - 1 - i) * 8)) & 0xFF); + + return OK; +} + + + +/*********** NEW API *************/ + +/** + * Convert a value of an id in a bitmask with a 1 in the position of the value + * of the id + * @param id Value of the ID to convert + * @param mask pointer to the bitmask that will be updated with the value of id + * @param size dimension in bytes of mask + * @return OK if success or ERROR_OP_NOT_ALLOW if size of mask is not enough to + * contain ID + */ +int fromIDtoMask(u8 id, u8 *mask, int size) +{ + if (((int)((id) / 8)) < size) { + pr_info("%s: ID = %d Index = %d Position = %d !\n", + __func__, id, ((int)((id) / 8)), (id % 8)); + mask[((int)((id) / 8))] |= 0x01 << (id % 8); + return OK; + } else { + pr_err("%s: Bitmask too small! Impossible contain ID = %d %d>=%d! ERROR %08X\n", + __func__, id, ((int)((id) / 8)), size, + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTool.h b/drivers/input/touchscreen/stm/fts_lib/ftsTool.h new file mode 100644 index 000000000000..284ef6c9cc92 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTool.h @@ -0,0 +1,58 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Utility Functions * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTool.h + * \brief Contains all the definitions to support common operations inside the + * driver + */ + +#ifndef FTS_TOOL_H +#define FTS_TOOL_H + +char *printHex(char *label, u8 *buff, int count, u8 *result, int size); +int u8ToU16(u8 *src, u16 *dst); +int u8ToU16_be(u8 *src, u16 *dst); +int u8ToU16n(u8 *src, int src_length, u16 *dst); +int u16ToU8(u16 src, u8 *dst); +int u16ToU8_be(u16 src, u8 *dst); +int u16ToU8n_be(u16 *src, int src_length, u8 *dst); +int u8ToU32(u8 *src, u32 *dst); +int u8ToU32_be(u8 *src, u32 *dst); +int u32ToU8(u32 src, u8 *dst); +int u32ToU8_be(u32 src, u8 *dst); +int u8ToU64_be(u8 *src, u64 *dest, int size); +int u64ToU8_be(u64 src, u8 *dest, int size); +int attempt_function(int (*code)(void), unsigned long wait_before_retry, int + retry_count); +int senseOn(void); +int senseOff(void); +void print_frame_short(char *label, short **matrix, int row, int column); +short **array1dTo2d_short(short *data, int size, int columns); +void print_frame_u16(char *label, u16 **matrix, int row, int column); +u16 **array1dTo2d_u16(u16 *data, int size, int columns); +u8 **array1dTo2d_u8(u8 *data, int size, int columns); +i8 **array1dTo2d_i8(i8 *data, int size, int columns); +void print_frame_u8(char *label, u8 **matrix, int row, int column); +void print_frame_i8(char *label, i8 **matrix, int row, int column); +void print_frame_u32(char *label, u32 **matrix, int row, int column); +void print_frame_int(char *label, int **matrix, int row, int column); +int cleanUp(int enableTouch); +int flushFIFO(void); + +/* New API */ +int fromIDtoMask(u8 id, u8 *mask, int size); + +#endif diff --git a/drivers/input/touchscreen/stm/fts_limits.h b/drivers/input/touchscreen/stm/fts_limits.h new file mode 100644 index 000000000000..5ecfa546b5b9 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_limits.h @@ -0,0 +1,1064 @@ +/*! +* \file fts_limits.h +* \brief Contains the size and the byte array of the production test limit file which contains thresholds used to test data +*/ + +#ifndef FTS_LIMITS_H +#define FTS_LIMITS_H +//This is an auto generated header file +//--->Remember to change the name of the two variables!<--- +const uint32_t myArray2_size = 16725; ///< size of the array containing the production limit file + +/** + * Array containing the production limit file + */ +const uint8_t myArray2[] = { + 0x2A, 0x53, 0x54, 0x4F, 0x50, 0x5F, 0x4F, 0x4E, 0x5F, 0x46, 0x41, 0x49, 0x4C, 0x2C, 0x31, 0x2C, + 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x53, 0x54, 0x4F, 0x50, 0x5F, 0x4F, 0x4E, 0x5F, 0x45, 0x52, 0x52, + 0x4F, 0x52, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, + 0x46, 0x57, 0x5F, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x30, 0x0A, + 0x2A, 0x53, 0x53, 0x5F, 0x49, 0x58, 0x31, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x57, 0x2C, + 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x46, 0x4F, + 0x52, 0x43, 0x45, 0x5F, 0x57, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x53, 0x53, 0x5F, + 0x49, 0x58, 0x31, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x57, 0x2C, 0x31, 0x2C, 0x31, 0x0A, + 0x32, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, + 0x57, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x52, 0x41, 0x57, 0x5F, + 0x44, 0x41, 0x54, 0x41, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, + 0x0A, 0x31, 0x30, 0x30, 0x30, 0x2C, 0x31, 0x35, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, + 0x52, 0x41, 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x47, 0x41, 0x50, 0x2C, 0x31, 0x2C, 0x31, + 0x0A, 0x33, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, + 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, + 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, + 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, + 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, + 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, + 0x43, 0x58, 0x32, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x37, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52, + 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x36, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, + 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, + 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x32, 0x37, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A, + 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, + 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, + 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, + 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, + 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x37, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, + 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, + 0x4F, 0x52, 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x36, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, + 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x32, 0x37, + 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, + 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, + 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, + 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x52, 0x41, + 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, + 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, + 0x59, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, + 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, + 0x58, 0x32, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x4D, 0x41, 0x58, + 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, + 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x4D, + 0x49, 0x4E, 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x4D, 0x53, + 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x4D, 0x41, + 0x58, 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A, + 0x53, 0x53, 0x5F, 0x52, 0x41, 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x46, 0x4F, 0x52, 0x43, + 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x31, 0x30, + 0x30, 0x30, 0x2C, 0x31, 0x35, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x52, 0x41, 0x57, + 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x47, 0x41, 0x50, 0x2C, + 0x31, 0x2C, 0x31, 0x0A, 0x33, 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, + 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x31, 0x5F, 0x46, 0x4F, 0x52, + 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, + 0x2C, 0x36, 0x33, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, + 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, + 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, + 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, + 0x30, 0x0A, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, + 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, + 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, + 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, + 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, + 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, + 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, + 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, + 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, + 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, + 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, + 0x32, 0x2C, 0x31, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, + 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, + 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, + 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, + 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, + 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, + 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, + 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, + 0x45, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, + 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, 0x2A, 0x53, 0x53, + 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, + 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x31, + 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, + 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, + 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x2A, 0x53, 0x53, + 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, + 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x31, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, + 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, + 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, 0x44, + 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, + 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x46, 0x4F, + 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x30, 0x0A, 0x30, + 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, + 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, + 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, + 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, + 0x43, 0x58, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, + 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, + 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, + 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, + 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, + 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x52, 0x41, + 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, + 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x31, 0x30, 0x30, 0x30, 0x2C, 0x31, 0x35, + 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x52, 0x41, 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, + 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x47, 0x41, 0x50, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x33, + 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, + 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x31, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, + 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, 0x2A, + 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, + 0x49, 0x58, 0x32, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, 0x2C, + 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, + 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x53, 0x45, + 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x37, 0x0A, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, + 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x41, 0x44, + 0x4A, 0x5F, 0x48, 0x4F, 0x52, 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, 0x32, + 0x36, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, + 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, + 0x5F, 0x49, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, 0x2C, + 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, + 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, + 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, + 0x49, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, + 0x37, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, + 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, + 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52, 0x49, + 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, 0x32, 0x36, 0x0A, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, + 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, + 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, + 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, + 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, + 0x2C, 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, + 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x53, + 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x37, 0x0A, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, + 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, + 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, + 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52, 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, + 0x32, 0x36, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, + 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, + 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, + 0x2C, 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, + 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, + 0x5F, 0x43, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, + 0x32, 0x37, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, + 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, + 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, + 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52, + 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, 0x32, 0x36, 0x0A, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, + 0x2C, 0x32, 0x35, 0x35, 0x0A, +}; + +#endif diff --git a/drivers/input/touchscreen/stm/fts_proc.c b/drivers/input/touchscreen/stm/fts_proc.c new file mode 100644 index 000000000000..bd6ddf37f96a --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_proc.c @@ -0,0 +1,3485 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com * + ************************************************************************** + * * + * Utilities published in /proc/fts * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file fts_proc.c + * \brief contains the function and variables needed to publish a file node in + * the file system which allow to communicate with the IC from userspace + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/proc_fs.h> +#include <linux/fs.h> +#include <linux/seq_file.h> +#include <linux/delay.h> +#include <linux/uaccess.h> +#include "fts.h" +#include "fts_lib/ftsCompensation.h" +#include "fts_lib/ftsCore.h" +#include "fts_lib/ftsIO.h" +#include "fts_lib/ftsError.h" +#include "fts_lib/ftsFrame.h" +#include "fts_lib/ftsFlash.h" +#include "fts_lib/ftsTest.h" +#include "fts_lib/ftsTime.h" +#include "fts_lib/ftsTool.h" + + +#define DRIVER_TEST_FILE_NODE "driver_test" /* /< name of file node + * published */ +#define CHUNK_PROC 1024 /* /< Max chunk of data printed on + * the sequential file in each + * iteration */ +#define DIAGNOSTIC_NUM_FRAME 10 /* /< number of frames reading + * iterations during the diagnostic + * test */ + + + +/** @defgroup proc_file_code Proc File Node + * @ingroup file_nodes + * The /proc/fts/driver_test file node provide expose the most important API + * implemented into the driver to execute any possible operation into the IC \n + * Thanks to a series of Operation Codes, each of them, with a different set of + * parameter, it is possible to select a function to execute\n + * The result of the function is usually returned into the shell as an ASCII + * hex string where each byte is encoded in two chars.\n + * @{ + */ + +/* Bus operations */ +#define CMD_READ 0x00 /* /< I2C/SPI read: need + * to pass: byteToRead1 + * byteToRead0 + * (optional) dummyByte + * */ +#define CMD_WRITE 0x01 /* /< I2C/SPI write: + * need to pass: cmd[0] + * cmd[1] … + * cmd[cmdLength-1] */ +#define CMD_WRITEREAD 0x02 /* /< I2C/SPI writeRead: + * need to pass: cmd[0] + * cmd[1] … + * cmd[cmdLength-1] + * byteToRead1 + * byteToRead0 dummyByte + * */ +#define CMD_WRITETHENWRITEREAD 0x03 /* /< I2C/SPI write then + * writeRead: need to + * pass: cmdSize1 + * cmdSize2 cmd1[0] + * cmd1[1] … + * cmd1[cmdSize1-1] + * cmd2[0] cmd2[1] … + * cmd2[cmdSize2-1] + * byteToRead1 + * byteToRead0 */ +#define CMD_WRITEU8UX 0x04 + /* /< I2C/SPI + * writeU8UX: + * need to pass: cmd + * addrSize addr[0] … + * addr[addrSize-1] + * data[0] data[1] … */ +#define CMD_WRITEREADU8UX 0x05 /* /< I2C/SPI + * writeReadU8UX: need + * to pass: cmd addrSize + * addr[0] … + * addr[addrSize-1] + * byteToRead1 + * byteToRead0 + * hasDummyByte */ +#define CMD_WRITEU8UXTHENWRITEU8UX 0x06 + /* /< I2C/SPI writeU8UX + * then writeU8UX: need + * to pass: cmd1 + * addrSize1 cmd2 + * addrSize2 addr[0] … + * addr[addrSize1+ + * addrSize2-1] + * data[0] data[1] … */ +#define CMD_WRITEU8UXTHENWRITEREADU8UX 0x07 /* /< I2C/SPI writeU8UX + * then writeReadU8UX: + * need to pass: cmd1 + * addrSize1 cmd2 + * addrSize2 addr[0] … + * addr[addrSize1+ + * addrSize2-1] + * byteToRead1 + * byteToRead0 + * hasDummybyte */ +#define CMD_GETLIMITSFILE 0x08 /* /< Get the Production + * Limits File and print + * its content into the + * shell: need to pass: + * path(optional) + * otherwise select the + * approach chosen at + * compile time */ +#define CMD_GETFWFILE 0x09 /* /< Get the FW file + * and print its content + * into the shell: need + * to pass: path + * (optional) otherwise + * select the approach + * chosen at compile + * time */ +#define CMD_VERSION 0x0A /* /< Get the driver + * version and other + * driver setting info + * */ +#define CMD_READCONFIG 0x0B /* /< Read The config + * memory, need to pass: + * addr[0] addr[1] + * byteToRead0 + * byteToRead1 */ + + +/* GUI utils byte ver */ +#define CMD_READ_BYTE 0xF0 /* /< Byte output + * version of I2C/SPI + * read @see CMD_READ */ +#define CMD_WRITE_BYTE 0xF1 /* /< Byte output + * version of I2C/SPI + * write @see CMD_WRITE + * */ +#define CMD_WRITEREAD_BYTE 0xF2 /* /< Byte output + * version of I2C/SPI + * writeRead @see + * CMD_WRITEREAD */ +#define CMD_WRITETHENWRITEREAD_BYTE 0xF3 + /* /< Byte output + * version of I2C/SPI + * write then writeRead + * @see + * CMD_WRITETHENWRITEREAD + * */ +#define CMD_WRITEU8UX_BYTE 0xF4 /* /< Byte output + * version of I2C/SPI + * writeU8UX @see + * CMD_WRITEU8UX */ +#define CMD_WRITEREADU8UX_BYTE 0xF5 /* /< Byte output + * version of I2C/SPI + * writeReadU8UX @see + * CMD_WRITEREADU8UX */ +#define CMD_WRITEU8UXTHENWRITEU8UX_BYTE 0xF6 + /* /< Byte output + * version of I2C/SPI + * writeU8UX then + * writeU8UX @see + * CMD_WRITEU8UXTHENWRITEU8UX + * */ +#define CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE 0xF7 + /* /< Byte output + * version of I2C/SPI + * writeU8UX then + * writeReadU8UX @see + * CMD_WRITEU8UXTHENWRITEREADU8UX + * */ +#define CMD_GETLIMITSFILE_BYTE 0xF8 /* /< Byte output + * version of Production + * Limits File @see + * CMD_GETLIMITSFILE */ +#define CMD_GETFWFILE_BYTE 0xF9 /* /< Byte output + * version of FW file + * need to pass: @see + * CMD_GETFWFILE */ +#define CMD_VERSION_BYTE 0xFA /* /< Byte output + * version of driver + * version and setting + * @see CMD_VERSION */ +#define CMD_CHANGE_OUTPUT_MODE 0xFF /* /< Select the output + * mode of the + * scriptless protocol, + * need to pass: + * bin_output = 1 data + * returned as binary, + * bin_output =0 data + * returned as hex + * string */ + +/* Core/Tools */ +#define CMD_POLLFOREVENT 0x11 /* /< Poll the FIFO for + * an event: need to + * pass: eventLength + * event[0] event[1] … + * event[eventLength-1] + * timeToWait1 + * timeToWait0 */ +#define CMD_SYSTEMRESET 0x12 /* /< System Reset */ +#define CMD_CLEANUP 0x13 /* /< Perform a system + * reset and optionally + * re-enable the + * scanning, need to + * pass: enableTouch */ +#define CMD_POWERCYCLE 0x14 /* /< Execute a power + * cycle toggling the + * regulators */ +#define CMD_READSYSINFO 0x15 /* /< Read the System + * Info information from + * the framebuffer, need + * to pass: doRequest */ +#define CMD_FWWRITE 0x16 + /* /< Write a FW + * command: need to + * pass: cmd[0] cmd[1] + * … cmd[cmdLength-1] */ +#define CMD_INTERRUPT 0x17 /* /< Allow to enable or + * disable the + * interrupts, need to + * pass: enable (if 1 + * will enable the + * interrupt) */ + +/* Frame */ +#define CMD_GETFORCELEN 0x20 /* /< Get the number of + * Force channels */ +#define CMD_GETSENSELEN 0x21 /* /< Get the number of + * Sense channels */ +#define CMD_GETMSFRAME 0x23 /* /< Get a MS frame: + * need to pass: + * MSFrameType */ +#define CMD_GETSSFRAME 0x24 /* /< Get a SS frame: + * need to pass: + * SSFrameType */ + +/* Compensation */ +#define CMD_REQCOMPDATA 0x30 /* /< Request Init data: + * need to pass: type */ +#define CMD_READCOMPDATAHEAD 0x31 /* /< Read Init data + * header: need to pass: + * type */ +#define CMD_READMSCOMPDATA 0x32 /* /< Read MS Init data: + * need to pass: type */ +#define CMD_READSSCOMPDATA 0x33 /* /< Read SS Init data: + * need to pass: type */ +#define CMD_READTOTMSCOMPDATA 0x35 /* /< Read Tot MS Init + * data: need to pass: + * type */ +#define CMD_READTOTSSCOMPDATA 0x36 /* /< Read Tot SS Init + * data: need to pass: + * type */ +#define CMD_READSENSCOEFF 0x37 /* /< Read MS and SS + * Sensitivity + * Calibration + * Coefficients */ + +/* FW Update */ +#define CMD_GETFWVER 0x40 /* /< Get the FW version + * of the IC */ +#define CMD_FLASHUNLOCK 0x42 /* /< Unlock the flash + * */ +#define CMD_READFWFILE 0x43 /* /< Try to read the FW + * file, need to pass: + * keep_cx */ +#define CMD_FLASHPROCEDURE 0x44 /* /< Perform a full + * flashing procedure: + * need to pass: force + * keep_cx */ +#define CMD_FLASHERASEUNLOCK 0x45 /* /< Unlock the erase + * of the flash */ +#define CMD_FLASHERASEPAGE 0x46 + /* /< Erase page by page + * the flash, need to + * pass: keep_cx, if + * keep_cx>SKIP_PANEL_INIT + * Panel Init Page will + * be skipped, if + * >SKIP_PANEL_CX_INIT + * Cx and Panel Init + * Pages will be skipped + * otherwise if + * =ERASE_ALL all the + * pages will be deleted + * */ + +/* MP test */ +#define CMD_ITOTEST 0x50 /* /< Perform an ITO + * test */ +#define CMD_INITTEST 0x51 /* /< Perform an + * Initialization test: + * need to pass: type */ +#define CMD_MSRAWTEST 0x52 /* /< Perform MS raw + * test: need to pass + * stop_on_fail */ +#define CMD_MSINITDATATEST 0x53 /* /< Perform MS Init + * data test: need to + * pass stop_on_fail */ +#define CMD_SSRAWTEST 0x54 /* /< Perform SS raw + * test: need to pass + * stop_on_fail */ +#define CMD_SSINITDATATEST 0x55 /* /< Perform SS Init + * data test: need to + * pass stop_on_fail */ +#define CMD_MAINTEST 0x56 /* /< Perform a full + * Mass production test: + * need to pass + * stop_on_fail saveInit + * */ +#define CMD_FREELIMIT 0x57 /* /< Free (if any) + * limit file which was + * loaded during any + * test procedure */ + +/* Diagnostic */ +#define CMD_DIAGNOSTIC 0x60 /* /< Perform a series + * of commands and + * collect severals data + * to detect any + * malfunction */ + +#define CMD_CHANGE_SAD 0x70 /* /< Allow to change + * the SAD address (for + * debugging) */ + +/* Debug functionalities requested by Google for B1 Project */ +#define CMD_TRIGGER_FORCECAL 0x80 /* /< Trigger manually + * forcecal for MS and + * SS */ +#define CMD_BASELINE_ADAPTATION 0x81 /* /< Enable/Disable + * Baseline adaptation, + * need to pass: enable + * */ +#define CMD_FREQ_HOP 0x82 /* /< Enable/Disable + * Frequency hopping, + * need to pass: enable + * */ +#define CMD_SET_OPERATING_FREQ 0x83 /* /< Set a defined + * scanning frequency in + * Hz passed as 4 bytes + * in big endian, need + * to pass: freq3 freq2 + * freq1 freq0 */ +#define CMD_READ_SYNC_FRAME 0x84 + /* /< Read Sync Frame + * which contain MS and + * SS data, need to + * pass: frameType (this + * parameter can be + * LOAD_SYNC_FRAME_STRENGTH + * or LOAD_SYNC_FRAME_BASELINE) + * */ + + +#define CMD_TP_SENS_MODE 0x90 /* /< Enter/Exit in the + * TP Sensitivity + * Calibration mode, + * need to pass: enter + * (optional)saveGain */ +#define CMD_TP_SENS_SET_SCAN_MODE 0x91 /* /< Set scan mode type + * which should be used + * for the test before + * the stimpad is down, + * need to pass: type */ +#define CMD_TP_SENS_PRECAL_SS 0x92 /* /< Perform Pre + * Calibration for SS + * steps when stimpad is + * down */ +#define CMD_TP_SENS_PRECAL_MS 0x93 /* /< Perform Pre + * Calibration for MS + * steps when stimpad is + * down */ +#define CMD_TP_SENS_POSTCAL_MS 0x94 /* /< Perform Post + * Calibration for MS + * steps when stimpad is + * down */ +#define CMD_TP_SENS_STD 0x95 /* /< Compute the + * Standard deviation of + * a certain number of + * frames, need to pass: + * numFrames */ + +#define CMD_FORCE_TOUCH_ACTIVE 0xA0 /* /< Prevent the driver + * from transitioning + * the ownership of the + * bus to SLPI + */ + +static u8 bin_output; /* /< Select the output type of the scriptless + * protocol (binary = 1 or hex string = 0) */ +/** @}*/ + +/** @defgroup scriptless Scriptless Protocol + * @ingroup proc_file_code + * Scriptless Protocol allows ST Software (such as FingerTip Studio etc) to + * communicate with the IC from an user space. + * This mode gives access to common bus operations (write, read etc) and + * support additional functionalities. \n + * The protocol is based on exchange of binary messages included between a + * start and an end byte + * @{ + */ + +#define MESSAGE_START_BYTE 0x7B /* /< start byte of each message + * transferred in Scriptless Mode */ +#define MESSAGE_END_BYTE 0x7D /* /< end byte of each message + * transferred in Scriptless Mode */ +#define MESSAGE_MIN_HEADER_SIZE 8 /* /< minimun number of bytes of the + * structure of a messages exchanged + * with host (include start/end byte, + * counter, actions, msg_size) */ + +/** + * Possible actions that can be requested by an host + */ +typedef enum { + ACTION_WRITE = (u16) 0x0001, /* /< Bus Write + * */ + ACTION_READ = (u16) 0x0002, /* /< Bus Read + * */ + ACTION_WRITE_READ = (u16) 0x0003, /* /< Bus Write + * followed by a + * Read */ + ACTION_GET_VERSION = (u16) 0x0004, /* /< Get + * Version of + * the protocol + * (equal to the + * first 2 bye + * of driver + * version) */ + ACTION_WRITEU8UX = (u16) 0x0011, /* /< Bus Write + * with support + * to different + * address size + * */ + ACTION_WRITEREADU8UX = (u16) 0x0012, /* /< Bus + * writeRead + * with support + * to different + * address size + * */ + ACTION_WRITETHENWRITEREAD = (u16) 0x0013, /* /< Bus write + * followed by a + * writeRead */ + ACTION_WRITEU8XTHENWRITEREADU8UX = (u16) 0x0014, /* /< Bus write + * followed by a + * writeRead + * with support + * to different + * address size + * */ + ACTION_WRITEU8UXTHENWRITEU8UX = (u16) 0x0015, /* /< Bus write + * followed by a + * write with + * support to + * different + * address size + * */ + ACTION_GET_FW = (u16) 0x1000, /* /< Get Fw + * file content + * used by the + * driver */ + ACTION_GET_LIMIT = (u16) 0x1001 /* /< Get Limit + * File content + * used by the + * driver */ +} Actions; + +/** + * Struct used to contain info of the message received by the host in + * Scriptless mode + */ +typedef struct { + u16 msg_size; /* /< total size of the message in bytes */ + u16 counter; /* /< counter ID to identify a message */ + Actions action; /* /< type of operation requested by the host @see + * Actions */ + u8 dummy; /* /< (optional)in case of any kind of read operations, + * specify if the first byte is dummy */ +} Message; + +/** @}*/ + + + +extern TestToDo tests; +extern SysInfo systemInfo; + +static int limit; /* /< store the amount of data to print into the + * shell */ +static int chunk; /* /< store the chuk of data that should be printed in + * this iteration */ +static int printed; /* /< store the amount of data already printed in the + * shell */ +static struct proc_dir_entry *fts_dir; /* /< reference to the directory + * fts under /proc */ +static u8 *driver_test_buff; /* /< pointer to an array of bytes used + * to store the result of the function + * executed */ +char buf_chunk[CHUNK_PROC] = { 0 }; /* /< buffer used to store the message + * info received */ +static Message mess = { 0 }; /* /< store the information of the Scriptless + * message received */ + + +/************************ SEQUENTIAL FILE UTILITIES **************************/ +/** + * This function is called at the beginning of the stream to a sequential file + * or every time into the sequential were already written PAGE_SIZE bytes and + * the stream need to restart + * @param s pointer to the sequential file on which print the data + * @param pos pointer to the offset where write the data + * @return NULL if there is no data to print or the pointer to the beginning of + * the data that need to be printed + */ +static void *fts_seq_start(struct seq_file *s, loff_t *pos) +{ + pr_info("%s: Entering start(), pos = %lld limit = %d printed = %d\n", + __func__, *pos, limit, printed); + + if (driver_test_buff == NULL && *pos == 0) { + int size = 13 * sizeof(u8); + + pr_info("%s: No data to print!\n", __func__); + driver_test_buff = (u8 *)kmalloc(size, GFP_KERNEL); + limit = scnprintf(driver_test_buff, + size, + "{ %08X }\n", ERROR_OP_NOT_ALLOW); + /* pr_err("%s: len = %d driver_test_buff = %s\n", + * __func__, limit, driver_test_buff); */ + } else { + if (*pos != 0) + *pos += chunk - 1; + + if (*pos >= limit) + /* pr_err("%s: Apparently, we're done.\n", __func__); */ + return NULL; + } + + chunk = CHUNK_PROC; + if (limit - *pos < CHUNK_PROC) + chunk = limit - *pos; + /* pr_err("%s: In start(), + * updated pos = %Ld limit = %d printed = %d chunk = %d\n", + * __func__, *pos, limit, printed, chunk); */ + memset(buf_chunk, 0, CHUNK_PROC); + memcpy(buf_chunk, &driver_test_buff[(int)*pos], chunk); + + return buf_chunk; +} + +/** + * This function actually print a chunk amount of data in the sequential file + * @param s pointer to the sequential file where to print the data + * @param v pointer to the data to print + * @return 0 + */ +static int fts_seq_show(struct seq_file *s, void *v) +{ + /* pr_err("%s: In show()\n", __func__); */ + seq_write(s, (u8 *)v, chunk); + printed += chunk; + return 0; +} + +/** + * This function update the pointer and the counters to the next data to be + * printed + * @param s pointer to the sequential file where to print the data + * @param v pointer to the data to print + * @param pos pointer to the offset where write the next data + * @return NULL if there is no data to print or the pointer to the beginning of + * the next data that need to be printed + */ +static void *fts_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + /* int* val_ptr; */ + /* pr_err("%s: In next(), v = %X, pos = %Ld.\n", __func__, + * v, *pos); */ + (*pos) += chunk;/* increase my position counter */ + chunk = CHUNK_PROC; + + /* pr_err("%s: In next(), + * updated pos = %Ld limit = %d printed = %d\n", + * __func__, *pos, limit,printed); */ + if (*pos >= limit) /* are we done? */ + return NULL; + else if (limit - *pos < CHUNK_PROC) + chunk = limit - *pos; + + + memset(buf_chunk, 0, CHUNK_PROC); + memcpy(buf_chunk, &driver_test_buff[(int)*pos], chunk); + return buf_chunk; +} + + +/** + * This function is called when there are no more data to print the stream + *need to be terminated or when PAGE_SIZE data were already written into the + *sequential file + * @param s pointer to the sequential file where to print the data + * @param v pointer returned by fts_seq_next + */ +static void fts_seq_stop(struct seq_file *s, void *v) +{ + /* pr_err("%s: Entering stop().\n", __func__); */ + + if (v) { + /* pr_err("%s: v is %X.\n", __func__, v); */ + } else { + /* pr_err("%s: v is null.\n", __func__); */ + limit = 0; + chunk = 0; + printed = 0; + if (driver_test_buff != NULL) { + /* pr_err("%s: Freeing and clearing driver_test_buff.\n", + * __func__); */ + kfree(driver_test_buff); + driver_test_buff = NULL; + } else { + /* pr_err("%s: driver_test_buff is already null.\n", + * __func__); */ + } + } +} + +/** + * Struct where define and specify the functions which implements the flow for + * writing on a sequential file + */ +static const struct seq_operations fts_seq_ops = { + .start = fts_seq_start, + .next = fts_seq_next, + .stop = fts_seq_stop, + .show = fts_seq_show +}; + +/** + * This function open a sequential file + * @param inode Inode in the file system that was called and triggered this + * function + * @param file file associated to the file node + * @return error code, 0 if success + */ +static int fts_driver_test_open(struct inode *inode, struct file *file) +{ + struct fts_ts_info *info = dev_get_drvdata(getDev()); + int retval; + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + retval = -ENODEV; + goto exit; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + retval = -EBUSY; + goto exit; + } + + /* Allowing only a single process to open diag procfs node */ + if (info->diag_node_open == true) { + pr_err("%s: Blocking multiple open\n", __func__); + retval = -EBUSY; + goto unlock; + } + + retval = seq_open(file, &fts_seq_ops); + if(!retval) { + info->diag_node_open = true; + } + +unlock: + mutex_unlock(&info->diag_cmd_lock); +exit: + return retval; +}; + +/** + * This function closes a sequential file + * @param inode Inode in the file system that was called and triggered this + * function + * @param file file associated to the file node + * @return error code, 0 if success + */ +static int fts_driver_test_release(struct inode *inode, struct file *file) +{ + struct fts_ts_info *info = dev_get_drvdata(getDev()); + int retval; + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + retval = -ENODEV; + goto exit; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + retval = -EBUSY; + goto exit; + } + + retval = seq_release(inode, file); + info->diag_node_open = false; + + mutex_unlock(&info->diag_cmd_lock); +exit: + return retval; +} + + +/** + * This function reads a sequential file + * @param file file associated to the file node + * @param buf userspace buffer where the newly read data should be placed + * @param count size of the requested transfer. + * @param pos start position from which data should be written in the file. + * @return error code, 0 if success + */ +static ssize_t fts_driver_test_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + struct fts_ts_info *info = dev_get_drvdata(getDev()); + ssize_t bytes_read = -EINVAL; + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + bytes_read = -ENODEV; + goto exit; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + bytes_read = -EBUSY; + goto exit; + } + + bytes_read = seq_read(file, buf, count, pos); + + mutex_unlock(&info->diag_cmd_lock); +exit: + return bytes_read; +} + +/** + * This function moves the cursor position within a file. + * @param file file associated to the file node + * @param offset offset relative to the current file position. + * @param whence defines where to seek from. + * @return error code, 0 if success + */ +static loff_t fts_driver_test_lseek(struct file *file, loff_t offset, + int whence) +{ + struct fts_ts_info *info = dev_get_drvdata(getDev()); + loff_t retval; + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + retval = -ENODEV; + goto exit; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + retval = -EBUSY; + goto exit; + } + + retval = seq_lseek(file, offset, whence); + + mutex_unlock(&info->diag_cmd_lock); + +exit: + return retval; +} + +/*****************************************************************************/ + +/**************************** DRIVER TEST ************************************/ + +/** @addtogroup proc_file_code + * @{ + */ + +/** + * Receive the OP code and the inputs from shell when the file node is called, + * parse it and then execute the corresponding function + * echo cmd+parameters > /proc/fts/driver_test to execute the select command + * cat /proc/fts/driver_test to obtain the result into the + * shell \n + * the string returned in the shell is made up as follow: \n + * { = start byte \n + * the answer content and format strictly depend on the cmd executed. In + * general can be: an HEX string or a byte array (e.g in case of 0xF- commands) + * \n + * } = end byte \n + */ +static ssize_t fts_driver_test_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + int numberParam = 0; + struct fts_ts_info *info = dev_get_drvdata(getDev()); + char *p = NULL; + char *pbuf = NULL; + char path[100] = { 0 }; + int res = -1, j, index = 0; + int size = 6; + int temp, byte_call = 0; + u16 byteToRead = 0; + u32 fileSize = 0; + u8 *readData = NULL; + u8 *cmd = NULL; /* worst case needs count bytes */ + u32 *funcToTest = NULL; + u64 addr = 0; + MutualSenseFrame frameMS; + MutualSenseFrame deltas; + SelfSenseFrame frameSS; + + DataHeader dataHead; + MutualSenseData compData; + SelfSenseData comData; + TotMutualSenseData totCompData; + TotSelfSenseData totComData; + MutualSenseCoeff msCoeff; + SelfSenseCoeff ssCoeff; + int meanNorm = 0, meanEdge = 0; + + u64 address; + + Firmware fw; + LimitFile lim; + + if (!info) { + pr_err("%s: Unable to access driver data\n", __func__); + count = -ENODEV; + goto exit; + } + + if (!mutex_trylock(&info->diag_cmd_lock)) { + pr_err("%s: Blocking concurrent access\n", __func__); + count = -EBUSY; + goto exit; + } + + mess.dummy = 0; + mess.action = 0; + mess.msg_size = 0; + + if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) { + res = ERROR_BUS_WR; + pr_err("%s: bus is not accessible.\n", __func__); + if (driver_test_buff) + limit = scnprintf(driver_test_buff, size, "{ %08X }\n", + res); + goto ERROR; + } + + pbuf = kmalloc(count * sizeof(*pbuf), GFP_KERNEL); + if (!pbuf) { + res = ERROR_ALLOC; + goto ERROR; + } + + funcToTest = kmalloc(((count + 1) / 3) * sizeof(*funcToTest), + GFP_KERNEL); + if (!funcToTest) { + res = ERROR_ALLOC; + goto ERROR; + } + + /*for(temp = 0; temp<count; temp++){ + * pr_err("p[%d] = %02X\n", temp, p[temp]); + * }*/ + if (access_ok(buf, count) < OK || + copy_from_user(pbuf, buf, count) != 0) { + res = ERROR_ALLOC; + goto END; + } + + cmd = (u8 *)kmalloc_array(count, sizeof(u8), GFP_KERNEL); + if (cmd == NULL) { + res = ERROR_ALLOC; + pr_err("%s: Impossible allocate memory... ERROR %08X!\n", + __func__, res); + goto ERROR; + } + + p = pbuf; + if (count > MESSAGE_MIN_HEADER_SIZE - 1 && p[0] == MESSAGE_START_BYTE) { + pr_info("Enter in Byte Mode!\n"); + byte_call = 1; + mess.msg_size = (p[1] << 8) | p[2]; + mess.counter = (p[3] << 8) | p[4]; + mess.action = (p[5] << 8) | p[6]; + pr_info("Message received: size = %d, counter_id = %d, action = %04X\n", + mess.msg_size, mess.counter, mess.action); + size = MESSAGE_MIN_HEADER_SIZE + 2; /* +2 error code */ + if (count < mess.msg_size || p[count - 2] != MESSAGE_END_BYTE) { + pr_err("number of byte received or end byte wrong! msg_size = %d != %zu, last_byte = %02X != %02X ... ERROR %08X\n", + mess.msg_size, count, p[count - 1], + MESSAGE_END_BYTE, ERROR_OP_NOT_ALLOW); + res = ERROR_OP_NOT_ALLOW; + goto END; + } else { + numberParam = mess.msg_size - MESSAGE_MIN_HEADER_SIZE + + 1; /* +1 because put the internal + * op code */ + size = MESSAGE_MIN_HEADER_SIZE + 2; /* +2 send also + * the first 2 + * lsb of the + * error code */ + switch (mess.action) { + case ACTION_READ: + /* numberParam = + * mess.msg_size-MESSAGE_MIN_HEADER_SIZE+1; */ + cmd[0] = funcToTest[0] = CMD_READ_BYTE; + break; + + case ACTION_WRITE: + cmd[0] = funcToTest[0] = CMD_WRITE_BYTE; + break; + + case ACTION_WRITE_READ: + cmd[0] = funcToTest[0] = CMD_WRITEREAD_BYTE; + break; + + case ACTION_GET_VERSION: + cmd[0] = funcToTest[0] = CMD_VERSION_BYTE; + break; + + case ACTION_WRITETHENWRITEREAD: + cmd[0] = funcToTest[0] = + CMD_WRITETHENWRITEREAD_BYTE; + break; + + case ACTION_WRITEU8UX: + cmd[0] = funcToTest[0] = CMD_WRITEU8UX_BYTE; + break; + + case ACTION_WRITEREADU8UX: + cmd[0] = funcToTest[0] = CMD_WRITEREADU8UX_BYTE; + break; + + case ACTION_WRITEU8UXTHENWRITEU8UX: + cmd[0] = funcToTest[0] = + CMD_WRITEU8UXTHENWRITEU8UX_BYTE; + break; + + case ACTION_WRITEU8XTHENWRITEREADU8UX: + cmd[0] = funcToTest[0] = + CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE; + break; + + case ACTION_GET_FW: + cmd[0] = funcToTest[0] = CMD_GETFWFILE_BYTE; + break; + + case ACTION_GET_LIMIT: + cmd[0] = funcToTest[0] = CMD_GETLIMITSFILE_BYTE; + break; + + default: + pr_err("Invalid Action = %d ... ERROR %08X\n", + mess.action, ERROR_OP_NOT_ALLOW); + res = ERROR_OP_NOT_ALLOW; + goto END; + } + + if (numberParam - 1 != 0) + memcpy(&cmd[1], &p[7], numberParam - 1); + /* -1 because i need to exclude the cmd[0] */ + } + } else { + if (((count + 1) / 3) >= 1) { + sscanf(p, "%02X ", &funcToTest[0]); + p += 3; + cmd[0] = (u8)funcToTest[0]; + numberParam = 1; + } else { + res = ERROR_OP_NOT_ALLOW; + goto END; + } + + pr_info("functionToTest[0] = %02X cmd[0]= %02X\n", + funcToTest[0], cmd[0]); + switch (funcToTest[0]) { + case CMD_GETFWFILE: + case CMD_GETLIMITSFILE: + if (count - 2 - 1 > 1) { + numberParam = 2;/** the first byte is an hex + * string coded in three byte + * (2 chars for hex and the + * space) + * and -1 for the space at the + * end */ + sscanf(p, "%100s", path); + } + break; + + default: + for (; numberParam < (count + 1) / 3; numberParam++) { + sscanf(p, "%02X ", &funcToTest[numberParam]); + p += 3; + cmd[numberParam] = (u8)funcToTest[numberParam]; + pr_info("functionToTest[%d] = %02X cmd[%d]= %02X\n", + numberParam, funcToTest[numberParam], + numberParam, cmd[numberParam]); + } + } + } + + + fw.data = NULL; + lim.data = NULL; + + pr_info("Number of Parameters = %d\n", numberParam); + + /* elaborate input */ + if (numberParam >= 1) { + switch (funcToTest[0]) { + case CMD_VERSION_BYTE: + pr_info("%s: Get Version Byte\n", __func__); + byteToRead = 2; + mess.dummy = 0; + readData = (u8 *)kmalloc(byteToRead * sizeof(u8), + GFP_KERNEL); + size += byteToRead; + if (readData != NULL) { + readData[0] = (u8)(FTS_TS_DRV_VER >> 24); + readData[1] = (u8)(FTS_TS_DRV_VER >> 16); + pr_info("%s: Version = %02X%02X\n", + __func__, readData[0], readData[1]); + res = OK; + } else { + res = ERROR_ALLOC; + pr_err("%s: Impossible allocate memory... ERROR %08X\n", + __func__, res); + } + break; + + + case CMD_VERSION: + byteToRead = 2 * sizeof(u32); + mess.dummy = 0; + readData = (u8 *)kmalloc(byteToRead * sizeof(u8), + GFP_KERNEL); + u32ToU8_be(FTS_TS_DRV_VER, readData); + fileSize = 0; + /* first two bytes bitmask of features enabled in the + * IC, second two bytes bitmask of features enabled in + * the driver */ + +#ifdef FW_H_FILE + fileSize |= 0x00010000; +#endif + +#ifdef LIMITS_H_FILE + fileSize |= 0x00020000; +#endif + +#ifdef USE_ONE_FILE_NODE + fileSize |= 0x00040000; +#endif + +#ifdef FW_UPDATE_ON_PROBE + fileSize |= 0x00080000; +#endif + +#ifdef PRE_SAVED_METHOD + fileSize |= 0x00100000; +#endif + +#ifdef USE_GESTURE_MASK + fileSize |= 0x00100000; +#endif + +#ifdef I2C_INTERFACE + fileSize |= 0x00200000; +#endif + +#ifdef PHONE_KEY /* it is a feature enabled in the config of the chip */ + fileSize |= 0x00000100; +#endif + +#ifdef GESTURE_MODE + fromIDtoMask(FEAT_SEL_GESTURE, (u8 *)&fileSize, 4); +#endif + + +#ifdef GRIP_MODE + fromIDtoMask(FEAT_SEL_GRIP, (u8 *)&fileSize, 4); +#endif + +#ifdef CHARGER_MODE + fromIDtoMask(FEAT_SEL_CHARGER, (u8 *)&fileSize, 4); +#endif + +#ifdef GLOVE_MODE + fromIDtoMask(FEAT_SEL_GLOVE, (u8 *)&fileSize, 4); +#endif + + +#ifdef COVER_MODE + fromIDtoMask(FEAT_SEL_COVER, (u8 *)&fileSize, 4); +#endif + +#ifdef STYLUS_MODE + fromIDtoMask(FEAT_SEL_STYLUS, (u8 *)&fileSize, 4); +#endif + + u32ToU8_be(fileSize, &readData[4]); + res = OK; + size += (byteToRead * sizeof(u8)); + break; + + case CMD_WRITEREAD: + case CMD_WRITEREAD_BYTE: + if (numberParam >= 5) { /* need to pass: cmd[0] cmd[1] + * … cmd[cmdLength-1] + * byteToRead1 byteToRead0 + * dummyByte */ + temp = numberParam - 4; + if (cmd[numberParam - 1] == 0) + mess.dummy = 0; + else + mess.dummy = 1; + + u8ToU16_be(&cmd[numberParam - 3], &byteToRead); + pr_info("bytesToRead = %d\n", + byteToRead + mess.dummy); + + readData = (u8 *)kmalloc((byteToRead + + mess.dummy) * + sizeof(u8), + GFP_KERNEL); + res = fts_writeRead_heap(&cmd[1], temp, + readData, byteToRead + mess.dummy); + size += (byteToRead * sizeof(u8)); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_WRITE: + case CMD_WRITE_BYTE: + if (numberParam >= 2) { /* need to pass: cmd[0] cmd[1] + * … cmd[cmdLength-1] */ + temp = numberParam - 1; + + res = fts_write_heap(&cmd[1], temp); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READ: + case CMD_READ_BYTE: + if (numberParam >= 3) { /* need to pass: byteToRead1 + * byteToRead0 (optional) + * dummyByte */ + if (numberParam == 3 || + (numberParam == 4 && + cmd[numberParam - 1] == 0)) + mess.dummy = 0; + else + mess.dummy = 1; + u8ToU16_be(&cmd[1], &byteToRead); + readData = (u8 *)kmalloc((byteToRead + + mess.dummy) * + sizeof(u8), + GFP_KERNEL); + res = fts_read_heap(readData, byteToRead + + mess.dummy); + size += (byteToRead * sizeof(u8)); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_WRITETHENWRITEREAD: + case CMD_WRITETHENWRITEREAD_BYTE: + /* need to pass: cmdSize1 cmdSize2 cmd1[0] cmd1[1] … + * cmd1[cmdSize1-1] cmd2[0] cmd2[1] … cmd2[cmdSize2-1] + * byteToRead1 byteToRead0 */ + if (numberParam >= 6) { + u8ToU16_be(&cmd[numberParam - 2], &byteToRead); + readData = (u8 *)kmalloc(byteToRead * + sizeof(u8), + GFP_KERNEL); + res = fts_writeThenWriteRead_heap( + &cmd[3], cmd[1], + &cmd[3 + (int)cmd[1]], cmd[2], + readData, byteToRead); + size += (byteToRead * sizeof(u8)); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_WRITEU8UX: + case CMD_WRITEU8UX_BYTE: + /* need to pass: + * cmd addrSize addr[0] … addr[addrSize-1] + * data[0] data[1] … */ + if (numberParam >= 4) { + if (cmd[2] <= sizeof(u64)) { + u8ToU64_be(&cmd[3], &addr, cmd[2]); + pr_info("addr = %llx\n", addr); + res = fts_writeU8UX(cmd[1], cmd[2], + addr, + &cmd[3 + cmd[2]], + (numberParam - cmd[2] - 3)); + } else { + pr_err("Wrong address size!\n"); + res = ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + case CMD_WRITEREADU8UX: + case CMD_WRITEREADU8UX_BYTE: + /* need to pass: + * cmd addrSize addr[0] … addr[addrSize-1] + * byteToRead1 byteToRead0 hasDummyByte */ + if (numberParam >= 6) { + if (cmd[2] <= sizeof(u64)) { + u8ToU64_be(&cmd[3], &addr, cmd[2]); + u8ToU16_be(&cmd[numberParam - 3], + &byteToRead); + readData = (u8 *)kmalloc(byteToRead * + sizeof(u8), + GFP_KERNEL); + pr_info("addr = %llx byteToRead = %d\n", + addr, byteToRead); + res = fts_writeReadU8UX(cmd[1], cmd[2], + addr, readData, + byteToRead, + cmd[numberParam - 1]); + size += (byteToRead * sizeof(u8)); + } else { + pr_err("Wrong address size!\n"); + res = ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_WRITEU8UXTHENWRITEU8UX: + case CMD_WRITEU8UXTHENWRITEU8UX_BYTE: + /* need to pass: + * cmd1 addrSize1 cmd2 addrSize2 addr[0] … + * addr[addrSize1+addrSize2-1] data[0] data[1] … */ + if (numberParam >= 6) { + if ((cmd[2] + cmd[4]) <= sizeof(u64)) { + u8ToU64_be(&cmd[5], &addr, cmd[2] + + cmd[4]); + + pr_info("addr = %llx\n", addr); + res = fts_writeU8UXthenWriteU8UX(cmd[1], + cmd[2], cmd[3], + cmd[4], addr, + &cmd[5 + cmd[2] + cmd[4]], + (numberParam - cmd[2] + - cmd[4] - 5)); + } else { + pr_err("Wrong address size!\n"); + res = ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_WRITEU8UXTHENWRITEREADU8UX: + case CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE: + /* need to pass: + * cmd1 addrSize1 cmd2 addrSize2 addr[0] … + * addr[addrSize1+addrSize2-1] byteToRead1 byteToRead0 + * hasDummybyte */ + if (numberParam >= 8) { + if ((cmd[2] + cmd[4]) <= sizeof(u64)) { + u8ToU64_be(&cmd[5], &addr, cmd[2] + + cmd[4]); + pr_info("%s: cmd[5] = %02X, addr = %llx\n", + __func__, cmd[5], addr); + u8ToU16_be(&cmd[numberParam - 3], + &byteToRead); + readData = (u8 *)kmalloc(byteToRead * + sizeof(u8), + GFP_KERNEL); + res = fts_writeU8UXthenWriteReadU8UX( + cmd[1], cmd[2], cmd[3], cmd[4], + addr, + readData, byteToRead, + cmd[numberParam - 1]); + size += (byteToRead * sizeof(u8)); + } else { + pr_err("Wrong total address size!\n"); + res = ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + + break; + + case CMD_CHANGE_OUTPUT_MODE: + /* need to pass: bin_output */ + if (numberParam >= 2) { + bin_output = cmd[1]; + pr_info("Setting Scriptless output mode: %d\n", + bin_output); + res = OK; + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_FWWRITE: + if (numberParam >= 3) { /* need to pass: cmd[0] cmd[1] + * … cmd[cmdLength-1] */ + if (numberParam >= 2) { + temp = numberParam - 1; + res = fts_writeFwCmd_heap(&cmd[1], + temp); + } else { + pr_err("Wrong parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_INTERRUPT: + /* need to pass: enable */ + if (numberParam >= 2) { + if (cmd[1] == 1) + res = fts_enableInterrupt(); + else + res = fts_disableInterrupt(); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + case CMD_READCONFIG: + if (numberParam == 5) { /* need to pass: addr[0] + * addr[1] byteToRead1 + * byteToRead0 */ + byteToRead = ((funcToTest[3] << 8) | + funcToTest[4]); + readData = (u8 *)kmalloc(byteToRead * + sizeof(u8), + GFP_KERNEL); + res = readConfig((u16)((((u8)funcToTest[1] & + 0x00FF) << 8) + + ((u8)funcToTest[2] & + 0x00FF)), + readData, byteToRead); + size += (byteToRead * sizeof(u8)); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_POLLFOREVENT: + if (numberParam >= 5) { /* need to pass: eventLength + * event[0] event[1] … + * event[eventLength-1] + * timeTowait1 timeTowait0 */ + temp = (int)funcToTest[1]; + if (numberParam == 5 + (temp - 1) && + temp != 0) { + readData = (u8 *)kmalloc( + FIFO_EVENT_SIZE * sizeof(u8), + GFP_KERNEL); + res = pollForEvent( + (int *)&funcToTest[2], temp, + readData, + ((funcToTest[temp + 2] & + 0x00FF) << 8) + + (funcToTest[temp + 3] & + 0x00FF)); + if (res >= OK) + res = OK; /* pollForEvent + * return the + * number of + * error found + * */ + size += (FIFO_EVENT_SIZE * sizeof(u8)); + byteToRead = FIFO_EVENT_SIZE; + } else { + pr_err("Wrong parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_SYSTEMRESET: + res = fts_system_reset(); + + break; + + case CMD_READSYSINFO: + if (numberParam == 2) /* need to pass: doRequest */ + res = readSysInfo(funcToTest[1]); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + + break; + + case CMD_CLEANUP:/* TOUCH ENABLE/DISABLE */ + if (numberParam == 2) /* need to pass: enableTouch */ + res = cleanUp(funcToTest[1]); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + + break; + + case CMD_GETFORCELEN: /* read number Tx channels */ + temp = getForceLen(); + if (temp < OK) + res = temp; + else { + size += (1 * sizeof(u8)); + res = OK; + } + break; + + case CMD_GETSENSELEN: /* read number Rx channels */ + temp = getSenseLen(); + if (temp < OK) + res = temp; + else { + size += (1 * sizeof(u8)); + res = OK; + } + break; + + + case CMD_GETMSFRAME: + if (numberParam == 2) { + pr_info("Get 1 MS Frame\n"); + setScanMode(SCAN_MODE_ACTIVE, 0xFF); + mdelay(WAIT_FOR_FRESH_FRAMES); + setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + /* flushFIFO(); //delete the events related to + * some touch (allow to call this function while + * touching the screen without having a flooding + * of the FIFO) */ + res = getMSFrame3((MSFrameType)cmd[1], + &frameMS); + if (res < 0) + pr_err("Error while taking the MS frame... ERROR %08X\n", + res); + + else { + pr_info("The frame size is %d words\n", + res); + size += (res * sizeof(short) + 2); + /* +2 to add force and sense channels + * set res to OK because if getMSFrame + * is successful + * res = number of words read + */ + res = OK; + print_frame_short("MS frame =", + array1dTo2d_short( + frameMS.node_data, + frameMS.node_data_size, + frameMS.header.sense_node), + frameMS.header.force_node, + frameMS.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + /*read self raw*/ + case CMD_GETSSFRAME: + if (numberParam == 2) { + pr_info("Get 1 SS Frame\n"); + /* flushFIFO(); //delete the events related to + * some touch (allow to call this function while + * touching the screen without having a flooding + * of the FIFO) */ + setScanMode(SCAN_MODE_ACTIVE, 0xFF); + mdelay(WAIT_FOR_FRESH_FRAMES); + setScanMode(SCAN_MODE_ACTIVE, 0x00); + mdelay(WAIT_AFTER_SENSEOFF); + res = getSSFrame3((SSFrameType)cmd[1], + &frameSS); + + if (res < OK) + pr_err("Error while taking the SS frame... ERROR %08X\n", + res); + + else { + pr_info("The frame size is %d words\n", + res); + size += (res * sizeof(short) + 2); + /* +2 to add force and sense channels + * set res to OK because if getMSFrame + * is successful + * res = number of words read + */ + res = OK; + print_frame_short("SS force frame =", + array1dTo2d_short( + frameSS.force_data, + frameSS.header.force_node, + 1), + frameSS.header.force_node, 1); + print_frame_short("SS sense frame =", + array1dTo2d_short( + frameSS.sense_data, + frameSS.header.sense_node, + frameSS.header.sense_node), + 1, + frameSS.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_REQCOMPDATA: /* request comp data */ + if (numberParam == 2) { + pr_info("Requesting Compensation Data\n"); + res = requestCompensationData(cmd[1]); + + if (res < OK) + pr_err("Error requesting compensation data ERROR %08X\n", + res); + else + pr_info("Requesting Compensation Data Finished!\n"); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READCOMPDATAHEAD: /* read comp data header */ + if (numberParam == 2) { + pr_info("Requesting Compensation Data\n"); + res = requestCompensationData(cmd[1]); + if (res < OK) + pr_err("Error requesting compensation data ERROR %08X\n", + res); + else { + pr_info("Requesting Compensation Data Finished!\n"); + res = readCompensationDataHeader( + (u8)funcToTest[1], &dataHead, + &address); + if (res < OK) + pr_err("Read Compensation Data Header ERROR %08X\n", + res); + else { + pr_info("Read Compensation Data Header OK!\n"); + size += (1 * sizeof(u8)); + } + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + case CMD_READMSCOMPDATA:/* read mutual comp data */ + if (numberParam == 2) { + pr_info("Get MS Compensation Data\n"); + res = readMutualSenseCompensationData(cmd[1], + &compData); + + if (res < OK) + pr_err("Error reading MS compensation data ERROR %08X\n", + res); + else { + pr_info("MS Compensation Data Reading Finished!\n"); + size = ((compData.node_data_size + 10) * + sizeof(i8)); + print_frame_i8("MS Data (Cx2) =", + array1dTo2d_i8( + compData.node_data, + compData.node_data_size, + compData.header.sense_node), + compData.header.force_node, + compData.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READSSCOMPDATA: + if (numberParam == 2) { /* read self comp data */ + pr_info("Get SS Compensation Data...\n"); + res = readSelfSenseCompensationData(cmd[1], + &comData); + if (res < OK) + pr_err("Error reading SS compensation data ERROR %08X\n", + res); + else { + pr_info("SS Compensation Data Reading Finished!\n"); + size = ((comData.header.force_node + + comData.header.sense_node) * + 2 + 13) * + sizeof(i8); + print_frame_i8("SS Data Ix2_fm = ", + array1dTo2d_i8( + comData.ix2_fm, + comData.header.force_node, + comData.header.force_node), + 1, + comData.header.force_node); + print_frame_i8("SS Data Cx2_fm = ", + array1dTo2d_i8( + comData.cx2_fm, + comData.header.force_node, + comData.header.force_node), + 1, + comData.header.force_node); + print_frame_i8("SS Data Ix2_sn = ", + array1dTo2d_i8( + comData.ix2_sn, + comData.header.sense_node, + comData.header.sense_node), + 1, + comData.header.sense_node); + print_frame_i8("SS Data Cx2_sn = ", + array1dTo2d_i8( + comData.cx2_sn, + comData.header.sense_node, + comData.header.sense_node), + 1, + comData.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READTOTMSCOMPDATA: /* read mutual comp data */ + if (numberParam == 2) { + pr_info("Get TOT MS Compensation Data\n"); + res = readTotMutualSenseCompensationData(cmd[1], + &totCompData); + + if (res < OK) + pr_err("Error reading TOT MS compensation data ERROR %08X\n", + res); + else { + pr_info("TOT MS Compensation Data Reading Finished!\n"); + size = (totCompData.node_data_size * + sizeof(short) + 9); + print_frame_short("MS Data (TOT Cx) =", + array1dTo2d_short( + totCompData.node_data, + totCompData.node_data_size, + totCompData.header.sense_node), + totCompData.header.force_node, + totCompData.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READTOTSSCOMPDATA: + if (numberParam == 2) { /* read self comp data */ + pr_info("Get TOT SS Compensation Data...\n"); + res = readTotSelfSenseCompensationData(cmd[1], + &totComData); + if (res < OK) + pr_err("Error reading TOT SS compensation data ERROR %08X\n", + res); + else { + pr_info("TOT SS Compensation Data Reading Finished!\n"); + size = ((totComData.header.force_node + + totComData.header.sense_node) * + 2 * + sizeof(short) + 9); + print_frame_u16("SS Data TOT Ix_fm = ", + array1dTo2d_u16( + totComData.ix_fm, + totComData.header.force_node, + totComData.header.force_node), + 1, + totComData.header.force_node); + print_frame_short( + "SS Data TOT Cx_fm = ", + array1dTo2d_short( + totComData.cx_fm, + totComData.header.force_node, + totComData.header.force_node), + 1, + totComData.header.force_node); + print_frame_u16("SS Data TOT Ix_sn = ", + array1dTo2d_u16( + totComData.ix_sn, + totComData.header.sense_node, + totComData.header.sense_node), + 1, + totComData.header.sense_node); + print_frame_short( + "SS Data TOT Cx_sn = ", + array1dTo2d_short( + totComData.cx_sn, + totComData.header.sense_node, + totComData.header.sense_node), + 1, + totComData.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READSENSCOEFF: + /* read MS and SS Sensitivity Coefficients */ + pr_info("Get Sensitivity Calibration Coefficients...\n"); + res = readSensitivityCoefficientsData(&msCoeff, + &ssCoeff); + if (res < OK) + pr_err("Error reading Sensitivity Calibration Coefficients ERROR %08X\n", + res); + else { + pr_info("Sensitivity Calibration Coefficients Reading Finished!\n"); + size += (((msCoeff.node_data_size) + + ssCoeff.header.force_node + + ssCoeff.header.sense_node) * + sizeof(u8) + 4); + print_frame_u8("MS Sensitivity Coeff = ", + array1dTo2d_u8(msCoeff.ms_coeff, + msCoeff. + node_data_size, + msCoeff.header. + sense_node), + msCoeff.header.force_node, + msCoeff.header.sense_node); + print_frame_u8("SS Sensitivity Coeff force = ", + array1dTo2d_u8( + ssCoeff.ss_force_coeff, + ssCoeff.header. + force_node, 1), + ssCoeff.header.force_node, 1); + print_frame_u8("SS Sensitivity Coeff sense = ", + array1dTo2d_u8( + ssCoeff.ss_sense_coeff, + ssCoeff.header. + sense_node, + ssCoeff.header. + sense_node), 1, + ssCoeff.header.sense_node); + } + break; + + case CMD_GETFWVER: + size += (EXTERNAL_RELEASE_INFO_SIZE)*sizeof(u8); + break; + + case CMD_FLASHUNLOCK: + res = flash_unlock(); + if (res < OK) + pr_err("Impossible Unlock Flash ERROR %08X\n", + res); + else + pr_info("Flash Unlock OK!\n"); + break; + + case CMD_READFWFILE: + if (numberParam == 2) { /* read fw file */ + pr_info("Reading FW File...\n"); + res = readFwFile(info->board->fw_name, &fw, + funcToTest[1]); + if (res < OK) + pr_err("Error reading FW File ERROR %08X\n", + res); + else + pr_info("Read FW File Finished!\n"); + kfree(fw.data); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_FLASHPROCEDURE: + if (numberParam == 3) { /* flashing procedure */ + pr_info("Starting Flashing Procedure...\n"); + res = flashProcedure(info->board->fw_name, + cmd[1], + cmd[2]); + if (res < OK) + pr_err("Error during flash procedure ERROR %08X\n", + res); + else + pr_info("Flash Procedure Finished!\n"); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_FLASHERASEUNLOCK: + res = flash_erase_unlock(); + if (res < OK) + pr_err("Error during flash erase unlock... ERROR %08X\n", + res); + else + pr_info("Flash Erase Unlock Finished!\n"); + break; + + case CMD_FLASHERASEPAGE: + if (numberParam == 2) { /* need to pass: keep_cx */ + pr_info("Starting Flashing Page Erase...\n"); + res = flash_erase_page_by_page(cmd[1]); + if (res < OK) + pr_err("Error during flash page erase... ERROR %08X\n", + res); + else + pr_info("Flash Page Erase Finished!\n"); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + /*ITO TEST*/ + case CMD_ITOTEST: + res = production_test_ito(LIMITS_FILE, &tests); + break; + + /*Initialization*/ + case CMD_INITTEST: + if (numberParam == 2) + res = production_test_initialization(cmd[1]); + + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + case CMD_MSRAWTEST: /* MS Raw DATA TEST */ + if (numberParam == 2) /* need to specify if stopOnFail + * */ + res = production_test_ms_raw(LIMITS_FILE, + cmd[1], &tests); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_MSINITDATATEST:/* MS CX DATA TEST */ + if (numberParam == 2) /* need stopOnFail */ + res = production_test_ms_cx(LIMITS_FILE, cmd[1], + &tests); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_SSRAWTEST: /* SS RAW DATA TEST */ + if (numberParam == 2) /* need stopOnFail */ + res = production_test_ss_raw(LIMITS_FILE, + cmd[1], &tests); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_SSINITDATATEST:/* SS IX CX DATA TEST */ + if (numberParam == 2) /* need stopOnFail */ + res = production_test_ss_ix_cx(LIMITS_FILE, + cmd[1], &tests); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + /*PRODUCTION TEST*/ + case CMD_MAINTEST: + if (numberParam == 3) /* need to specify if stopOnFail + * and saveInit */ + res = production_test_main(LIMITS_FILE, cmd[1], + cmd[2], &tests); + else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_FREELIMIT: + res = freeCurrentLimitsFile(); + break; + + case CMD_POWERCYCLE: + res = fts_chip_powercycle(info); + break; + + case CMD_GETLIMITSFILE: + /* need to pass: path(optional) return error code + + * number of byte read otherwise GUI could not now how + * many byte read */ + if (numberParam >= 1) { + lim.data = NULL; + lim.size = 0; + if (numberParam == 1) + res = getLimitsFile(LIMITS_FILE, &lim); + else + res = getLimitsFile(path, &lim); + readData = lim.data; + fileSize = lim.size; + size += (fileSize * sizeof(u8)); + if (byte_call == 1) + size += sizeof(u32); /* transmit as + * first 4 bytes + * the size */ + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_GETLIMITSFILE_BYTE: + /* need to pass: byteToRead1 byteToRead0 */ + if (numberParam >= 3) { + lim.data = NULL; + lim.size = 0; + + u8ToU16_be(&cmd[1], &byteToRead); + addr = ((u64)byteToRead) * 4; /* number of + * words */ + + res = getLimitsFile(LIMITS_FILE, &lim); + + readData = lim.data; + fileSize = lim.size; + + if (fileSize > addr) { + pr_err("Limits dimension expected by Host is less than actual size: expected = %d, real = %d\n", + byteToRead, fileSize); + res = ERROR_OP_NOT_ALLOW; + } + + size += (addr * sizeof(u8)); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_GETFWFILE: + /* need to pass: from (optional) otherwise select the + * approach chosen at compile time */ + if (numberParam >= 1) { + if (numberParam == 1) + res = getFWdata(info->board->fw_name, + &readData, &fileSize); + else + res = getFWdata(path, &readData, + &fileSize); + + size += (fileSize * sizeof(u8)); + if (byte_call == 1) + size += sizeof(u32); /* transmit as + * first 4 bytes + * the size */ + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_GETFWFILE_BYTE: + /* need to pass: byteToRead1 byteToRead0 */ + if (numberParam == 3) { + u8ToU16_be(&cmd[1], &byteToRead); + addr = ((u64)byteToRead) * 4; /* number of + * words */ + res = getFWdata(info->board->fw_name, &readData, + &fileSize); + if (fileSize > addr) { + pr_err("FW dimension expected by Host is less than actual size: expected = %d, real = %d\n", + byteToRead, fileSize); + res = ERROR_OP_NOT_ALLOW; + } + + size += (addr * sizeof(u8)); /* return always + * the amount + * requested by + * host, if real + * size is + * smaller, the + * data are + * padded to + * zero */ + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + /* finish all the diagnostic command with a goto ERROR in order + * to skip the modification on driver_test_buff + * remember to set properly the limit and printed variables in + * order to make the seq_file logic to work */ + case CMD_DIAGNOSTIC: + index = 0; + size = 0; + fileSize = 256 * 1024 * sizeof(char); + driver_test_buff = (u8 *)kzalloc(fileSize, GFP_KERNEL); + readData = (u8 *)kmalloc((ERROR_DUMP_ROW_SIZE * + ERROR_DUMP_COL_SIZE) * + sizeof(u8), GFP_KERNEL); + if (driver_test_buff == NULL || readData == NULL) { + res = ERROR_ALLOC; + pr_err("Impossible allocate memory for buffers! ERROR %08X!\n", + res); + goto END; + } + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "DIAGNOSTIC TEST:\n1) I2C Test: "); + index += j; + + res = fts_writeReadU8UX(FTS_CMD_HW_REG_R, + ADDR_SIZE_HW_REG, ADDR_DCHIP_ID, + (u8 *)&temp, 2, + DUMMY_HW_REG); + if (res < OK) { + pr_err("Error during I2C test: ERROR %08X!\n", + res); + j = scnprintf(&driver_test_buff[index], + fileSize - index, "ERROR %08X\n", + res); + index += j; + res = ERROR_OP_NOT_ALLOW; + goto END_DIAGNOSTIC; + } + + temp &= 0xFFFF; + pr_info("Chip ID = %04X!\n", temp); + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "DATA = %04X, expected = %02X%02X\n", + temp, DCHIP_ID_1, + DCHIP_ID_0); + index += j; + if (temp != ((DCHIP_ID_1 << 8) | DCHIP_ID_0)) { + pr_err("Wrong CHIP ID, Diagnostic failed!\n"); + res = ERROR_OP_NOT_ALLOW; + goto END_DIAGNOSTIC; + } + + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "Present Driver Mode: %08X\n", + info->mode); + index += j; + + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "2) FW running: Sensing On..."); + index += j; + pr_info("Sensing On!\n"); + readData[0] = FTS_CMD_SCAN_MODE; + readData[1] = SCAN_MODE_ACTIVE; + readData[2] = 0x1; + fts_write_heap(readData, 3); + res = checkEcho(readData, 3); + if (res < OK) { + pr_err("No Echo received.. ERROR %08X !\n", + res); + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "No echo found... ERROR %08X!\n", + res); + index += j; + goto END_DIAGNOSTIC; + } else { + pr_info("Echo FOUND... OK!\n"); + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "Echo FOUND... OK!\n"); + index += j; + } + + pr_info("Reading Frames...!\n"); + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "3) Read Frames:\n"); + index += j; + for (temp = 0; temp < DIAGNOSTIC_NUM_FRAME; temp++) { + pr_info("Iteration n. %d...\n", temp + 1); + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "Iteration n. %d...\n", + temp + 1); + index += j; + for (addr = 0; addr < 3; addr++) { + switch (addr) { + case 0: + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "MS RAW FRAME ="); + index += j; + res |= getMSFrame3(MS_RAW, + &frameMS); + break; + case 2: + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "MS STRENGTH FRAME ="); + index += j; + res |= getMSFrame3(MS_STRENGTH, + &frameMS); + break; + case 1: + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "MS BASELINE FRAME ="); + index += j; + res |= getMSFrame3(MS_BASELINE, + &frameMS); + break; + } + if (res < OK) { + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "No data! ERROR %08X\n", + res); + index += j; + } else { + for (address = 0; address < + frameMS.node_data_size; + address++) { + if (address % + frameMS.header. + sense_node == 0) { + j = scnprintf( + &driver_test_buff + [index], + fileSize - + index, + "\n"); + index += j; + } + j = scnprintf( + &driver_test_buff + [index], + fileSize - index, + "%5d, ", + frameMS. + node_data[address]); + index += j; + } + j = scnprintf( + &driver_test_buff[index], + fileSize - index, "\n"); + index += j; + } + if (frameMS.node_data != NULL) + kfree(frameMS.node_data); + } + for (addr = 0; addr < 3; addr++) { + switch (addr) { + case 0: + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "SS RAW FRAME =\n"); + index += j; + res |= getSSFrame3(SS_RAW, + &frameSS); + break; + case 2: + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "SS STRENGTH FRAME =\n"); + index += j; + res |= getSSFrame3(SS_STRENGTH, + &frameSS); + break; + case 1: + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "SS BASELINE FRAME =\n"); + index += j; + res |= getSSFrame3(SS_BASELINE, + &frameSS); + break; + } + if (res < OK) { + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "No data! ERROR %08X\n", + res); + index += j; + } else { + int num; + short *data; + + num = frameSS.header.force_node; + data = frameSS.force_data; + for (address = 0; + address < num; + address++) { + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "%d\n", + data[address]); + index += j; + } + + num = frameSS.header.sense_node; + data = frameSS.sense_data; + for (address = 0; + address < num; + address++) { + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "%d, ", + data[address]); + index += j; + } + j = scnprintf( + &driver_test_buff[index], + fileSize - index, "\n"); + index += j; + } + if (frameSS.force_data != NULL) + kfree(frameSS.force_data); + if (frameSS.sense_data != NULL) + kfree(frameSS.sense_data); + } + } + + + pr_info("Reading error info...\n"); + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "4) FW INFO DUMP: "); + index += j; + temp = dumpErrorInfo(readData, ERROR_DUMP_ROW_SIZE * + ERROR_DUMP_COL_SIZE); + /* OR to detect if there are failures also in the + * previous reading of frames and write the correct + * result */ + if (temp < OK) { + pr_err("Error during dump: ERROR %08X!\n", + res); + j = scnprintf(&driver_test_buff[index], + fileSize - index, "ERROR %08X\n", + temp); + index += j; + } else { + pr_info("DUMP OK!\n"); + for (temp = 0; temp < ERROR_DUMP_ROW_SIZE * + ERROR_DUMP_COL_SIZE; temp++) { + if (temp % ERROR_DUMP_COL_SIZE == 0) { + j = scnprintf( + &driver_test_buff[index], + fileSize - index, + "\n%2d - ", + temp / ERROR_DUMP_COL_SIZE); + index += j; + } + j = scnprintf(&driver_test_buff[index], + fileSize - index, "%02X ", + readData[temp]); + index += j; + } + } + res |= temp; + +END_DIAGNOSTIC: + if (res < OK) { + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "\nRESULT = FAIL\n"); + index += j; + } else { + j = scnprintf(&driver_test_buff[index], + fileSize - index, + "\nRESULT = FINISHED\n"); + index += j; + } + /* the sting is already terminated with the null char by + * scnprintf */ + limit = index; + printed = 0; + goto ERROR; + break; + + case CMD_CHANGE_SAD: + res = changeSAD(cmd[1]); + break; + + case CMD_TRIGGER_FORCECAL: + cmd[0] = CAL_MS_TOUCH | CAL_SS_TOUCH; + cmd[1] = 0x00; + fts_disableInterrupt(); + res = writeSysCmd(SYS_CMD_FORCE_CAL, cmd, 2); + res |= fts_enableInterrupt(); + if (res < OK) + pr_err("can not trigger Force Cal! ERROR %08X\n", + res); + else + pr_info("MS and SS force cal triggered!\n"); + break; + + case CMD_BASELINE_ADAPTATION: + /* need to pass: enable */ + if (numberParam == 2) { + if (cmd[1] == 0x01) + pr_info("Enabling Baseline adaptation...\n"); + else { + pr_info("Disabling Baseline adaptation...\n"); + cmd[1] = 0x00; /* set to zero to + * disable baseline + * adaptation */ + } + + res = writeConfig(ADDR_CONFIG_AUTOCAL, &cmd[1], + 1); + if (res < OK) + pr_err("Baseline adaptation operation FAILED! ERROR %08X\n", + res); + else + pr_info("Baseline adaptation operation OK!\n"); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_FREQ_HOP: + /* need to pass: enable */ + if (numberParam == 2) { + pr_info("Reading MNM register...\n"); + res = readConfig(ADDR_CONFIG_MNM, &cmd[2], 1); + if (res < OK) { + pr_err("Reading MNM register... ERROR %08X!\n", + res); + break; + } + + if (cmd[1] == 0x01) { + pr_info("Enabling Frequency Hopping... %02X => %02X\n", + cmd[2], cmd[2] | 0x01); + cmd[2] |= 0x01; /* set bit 0 to enable + * Frequency Hopping */ + } else { + pr_info("Disabling Frequency Hopping... %02X => %02X\n", + cmd[2], cmd[2] & (~0x01)); + cmd[2] &= (~0x01); /* reset bit 0 + * to disable + * Frequency + * Hopping */ + } + + res = writeConfig(ADDR_CONFIG_MNM, &cmd[2], 1); + if (res < OK) + pr_err("Frequency Hopping operation FAILED! ERROR %08X\n", + res); + else + pr_info("Frequency Hopping operation OK!\n"); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_READ_SYNC_FRAME: + /* need to pass: frameType (this parameter can be + * LOAD_SYNC_FRAME_STRENGTH or LOAD_SYNC_FRAME_BASELINE) + * */ + if (numberParam == 2) { + pr_info("Reading Sync Frame...\n"); + res = getSyncFrame(cmd[1], &frameMS, &frameSS); + if (res < OK) + pr_err("Error while taking the Sync Frame frame... ERROR %08X\n", + res); + + else { + pr_info("The total frames size is %d words\n", + res); + size += (res * sizeof(short) + 4); + /* +4 to add force and sense channels + * for MS and SS + * set res to OK because if getSyncFrame + * is successful + * res = number of words read + */ + res = OK; + + print_frame_short("MS frame =", + array1dTo2d_short( + frameMS.node_data, + frameMS.node_data_size, + frameMS.header.sense_node), + frameMS.header.force_node, + frameMS.header.sense_node); + print_frame_short("SS force frame =", + array1dTo2d_short( + frameSS.force_data, + frameSS.header.force_node, + 1), + frameSS.header.force_node, 1); + print_frame_short("SS sense frame =", + array1dTo2d_short( + frameSS.sense_data, + frameSS.header.sense_node, + frameSS.header.sense_node), + 1, + frameSS.header.sense_node); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_SET_OPERATING_FREQ: + /* need to pass: freq3 freq2 freq1 freq0 */ + if (numberParam == 5) { + res = fts_disableInterrupt(); + if (res >= OK) { + pr_info("Setting Scan Freq...\n"); + u8ToU32_be(&cmd[1], &fileSize); + /* fileSize is used just as container + * variable, sorry for the name! */ + + res = setActiveScanFrequency(fileSize); + if (res < OK) + pr_err("Error while setting the scan frequency... ERROR %08X\n", + res); + else { + /* setActiveScan Frequency leave + * the chip in reset state but + * with the new scan freq set */ + /* need to enable the scan mode + * and re-enable the interrupts + * */ + res |= setScanMode( + SCAN_MODE_LOCKED, + LOCKED_ACTIVE); + /* this is a choice to force + * the IC to use the freq set */ + res |= fts_enableInterrupt(); + pr_info("Setting Scan Freq... res = %08X\n", + res); + } + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + + break; + + case CMD_TP_SENS_MODE: + /* need to pass: enter (optional)saveGain */ + if (numberParam >= 2) { + if (numberParam == 2) + cmd[2] = 0; /* by default never save + * the gain (used only + * when exit) */ + + res = tp_sensitivity_mode(cmd[1], cmd[2]); + if (res < OK) + pr_err("Error while setting TP Sens mode... ERROR %08X\n", + res); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + case CMD_TP_SENS_SET_SCAN_MODE: + /* need to pass: scan_type, enableGains */ + if (numberParam == 3) { + res = tp_sensitivity_set_scan_mode(cmd[1], + cmd[2]); + /* this force the IC to lock in a scan mode */ + if (res < OK) + pr_err("Error while setting TP Sens scan mode... ERROR %08X\n", + res); + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + + break; + + case CMD_TP_SENS_PRECAL_SS: + /* need to pass: target1 target0 percentage(optional) */ + if (numberParam >= 3) { + if (numberParam > 3) + temp = cmd[3]; + else + temp = SENS_TEST_PERC_TARGET_PRECAL; + + pr_info("Setting target = %d and percentage = %d\n", + (cmd[1] << 8 | cmd[2]), temp); + + res = tp_sensitivity_test_pre_cal_ss(&frameSS, + (cmd[1] << 8 | + cmd[2]), + temp); + if (res < OK) + pr_err("Error while setting the scan frequency... ERROR %08X\n", + res); + + if ((frameSS.force_data != NULL) && + (frameSS.sense_data != NULL)) { + size += ((frameSS.header.force_node + + frameSS.header.sense_node) * + sizeof(short) + 2); + /*make error code positive to print the + * frame*/ + res &= (~0x80000000); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_TP_SENS_PRECAL_MS: + /* need to pass: target1 target0 calibrate + * percentage(optional) */ + if (numberParam >= 4) { + if (numberParam > 4) + temp = cmd[4]; + else + temp = SENS_TEST_PERC_TARGET_PRECAL; + + pr_info("Setting target = %d and percentage = %d\n", + (cmd[1] << 8 | cmd[2]), temp); + + res = tp_sensitivity_test_pre_cal_ms(&frameMS, + (cmd[1] << 8 | + cmd[2]), + temp); + if (res < OK) + pr_err("Error during TP Sensitivity Precal ... ERROR %08X\n", + res); + + if (cmd[3] != 0) { + pr_info("Computing gains with target = %d and saveGain = %d\n", + (cmd[1] << 8 | cmd[2]), cmd[3]); + temp = tp_sensitivity_compute_gains( + &frameMS, (cmd[1] << 8 | + cmd[2]), + cmd[3]); + if (temp < OK) + pr_err("Error during TP Sensitivity Calibration... ERROR %08X\n", + temp); + res |= temp; + } + + if (frameMS.node_data != NULL) { + size += (frameMS.node_data_size * + sizeof(short) + 2); + /*make error code positive to print the + * frame*/ + res &= (~0x80000000); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_TP_SENS_POSTCAL_MS: + /* need to pass: target1 target0 executeTest + * percentage(optional) */ + if (numberParam >= 4) { + if (cmd[3] != 0) { + if (numberParam > 4) + temp = cmd[4]; + else + temp = + SENS_TEST_PERC_TARGET_POSTCAL; + } else + temp = -1; + + pr_info("Setting target = %d and percentage = %d\n", + (cmd[1] << 8 | cmd[2]), temp); + + res = tp_sensitivity_test_post_cal_ms(&frameMS, + &deltas, + (cmd[1] << 8 | + cmd[2]), + temp, + &meanNorm, + &meanEdge); + if (res < OK) + pr_err("Error during TP Sensitivity Post Cal ... ERROR %08X\n", + res); + + /* processing for a proper printing on the shell + * */ + if ((frameMS.node_data != NULL) && + (deltas.node_data != NULL)) { + size += ((frameMS.node_data_size + + deltas.node_data_size) * + sizeof(short) + + 2 + 8);/* +2 force and + * sense len, +8 + * mean_normal/edge + * */ + /*make error code positive to print the + * frame*/ + res &= (~0x80000000); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + + case CMD_TP_SENS_STD: + /* need to pass: numFrames */ + if (numberParam >= 2) { + res = tp_sensitivity_test_std_ms(cmd[1], + &frameMS); + if (res < OK) + pr_err("Error during TP Sensitivity STD... ERROR %08X\n", + res); + + /* processing for a proper printing on the shell + * */ + if (frameMS.node_data != NULL) { + size += ((frameMS.node_data_size) * + sizeof(short) + 2); + /* +2 force and sense len */ + /*make error code positive to print the + * frame*/ + res &= (~0x80000000); + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + case CMD_FORCE_TOUCH_ACTIVE: + /* Single parameter indicates force touch state */ + if (numberParam == 2) { + if (cmd[1] > 1) { + pr_err("Parameter should be 1 or 0\n"); + res = ERROR_OP_NOT_ALLOW; + } else { + fts_set_bus_ref(info, + FTS_BUS_REF_FORCE_ACTIVE, + cmd[1]); + res = OK; + } + } else { + pr_err("Wrong number of parameters!\n"); + res = ERROR_OP_NOT_ALLOW; + } + break; + + default: + pr_err("COMMAND ID NOT VALID!!!\n"); + res = ERROR_OP_NOT_ALLOW; + break; + } + + /* res2 = fts_enableInterrupt(); + * the interrupt was disabled on purpose in this node because it + * can be used for testing procedure and between one step and + * another the interrupt wan to be kept disabled + * if (res2 < 0) { + * pr_err("stm_driver_test_show: ERROR %08X\n", + * (res2 | ERROR_ENABLE_INTER)); + * }*/ + } else { + pr_err("NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n"); + res = ERROR_OP_NOT_ALLOW; + } + +END: /* here start the reporting phase, assembling the data to send in the + * file node */ + if (driver_test_buff != NULL) { + pr_info("Consecutive echo on the file node, free the buffer with the previous result\n"); + kfree(driver_test_buff); + } + + if (byte_call == 0) { + size *= 2; + size += 2; /* add \n and \0 (terminator char) */ + } else { + if (bin_output != 1) { + size *= 2; /* need to code each byte as HEX string */ + size -= 1; /* start byte is just one, the extra + * byte of end byte taken by \n */ + } else + size += 1; /* add \n */ + } + + pr_info("Size = %d\n", size); + driver_test_buff = (u8 *)kzalloc(size, GFP_KERNEL); + pr_info("Finish to allocate memory!\n"); + if (driver_test_buff == NULL) { + pr_err("Unable to allocate driver_test_buff! ERROR %08X\n", + ERROR_ALLOC); + goto ERROR; + } + + if (byte_call == 0) { + index = 0; + index += scnprintf(&driver_test_buff[index], + size - index, "{ "); + index += scnprintf(&driver_test_buff[index], + size - index, "%08X", res); + if (res >= OK) { + /*all the other cases are already fine printing only the + * res.*/ + switch (funcToTest[0]) { + case CMD_VERSION: + case CMD_READ: + case CMD_WRITEREAD: + case CMD_WRITETHENWRITEREAD: + case CMD_WRITEREADU8UX: + case CMD_WRITEU8UXTHENWRITEREADU8UX: + case CMD_READCONFIG: + case CMD_POLLFOREVENT: + /* pr_err("Data = "); */ + if (mess.dummy == 1) + j = 1; + else + j = 0; + for (; j < byteToRead + mess.dummy; j++) { + /* pr_err("%02X ", readData[j]); */ + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", readData[j]); + /* this approach is much more faster */ + } + /* pr_err("\n"); */ + break; + case CMD_GETFWFILE: + case CMD_GETLIMITSFILE: + pr_info("Start To parse!\n"); + for (j = 0; j < fileSize; j++) { + /* pr_err("%02X ", readData[j]); */ + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", readData[j]); + } + pr_info("Finish to parse!\n"); + break; + case CMD_GETFORCELEN: + case CMD_GETSENSELEN: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)temp); + break; + case CMD_GETMSFRAME: + case CMD_TP_SENS_PRECAL_MS: + case CMD_TP_SENS_POSTCAL_MS: + case CMD_TP_SENS_STD: + + if (res != OK) + driver_test_buff[2] = '8'; + /* convert back error code to negative */ + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameMS.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameMS.header.sense_node); + + for (j = 0; j < frameMS.node_data_size; j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (frameMS.node_data[j] & 0xFF00) >> 8, + frameMS.node_data[j] & 0xFF); + } + + kfree(frameMS.node_data); + + if (funcToTest[0] == CMD_TP_SENS_POSTCAL_MS) { + /* print also mean and deltas */ + for (j = 0; j < deltas.node_data_size; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (deltas.node_data[j] & + 0xFF00) >> 8, + deltas.node_data[j] & + 0xFF); + } + kfree(deltas.node_data); + + index += scnprintf( + &driver_test_buff[index], + size - index, + "%08X", meanNorm); + + index += scnprintf( + &driver_test_buff[index], + size - index, + "%08X", meanEdge); + } + break; + case CMD_GETSSFRAME: + case CMD_TP_SENS_PRECAL_SS: + if (res != OK) + driver_test_buff[2] = '8'; + /* convert back error code to negative */ + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameSS.header.force_node); + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameSS.header.sense_node); + /* Copying self raw data Force */ + for (j = 0; j < frameSS.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (frameSS.force_data[j] & 0xFF00) >> 8, + frameSS.force_data[j] & 0xFF); + } + + /* Copying self raw data Sense */ + for (j = 0; j < frameSS.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (frameSS.sense_data[j] & 0xFF00) >> 8, + frameSS.sense_data[j] & 0xFF); + } + + kfree(frameSS.force_data); + kfree(frameSS.sense_data); + break; + + case CMD_READMSCOMPDATA: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)compData.header.type); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)compData.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)compData.header.sense_node); + + /* Cpying CX1 value */ + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + compData.cx1 & 0xFF); + + /* Copying CX2 values */ + for (j = 0; j < compData.node_data_size; j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + compData.node_data[j] & 0xFF); + } + + kfree(compData.node_data); + break; + + case CMD_READSSCOMPDATA: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)comData.header.type); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + comData.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + comData.header.sense_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + comData.f_ix1 & 0xFF); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + comData.s_ix1 & 0xFF); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + comData.f_cx1 & 0xFF); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + comData.s_cx1 & 0xFF); + + /* Copying IX2 Force */ + for (j = 0; j < comData.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + comData.ix2_fm[j] & 0xFF); + } + + /* Copying IX2 Sense */ + for (j = 0; j < comData.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + comData.ix2_sn[j] & 0xFF); + } + + /* Copying CX2 Force */ + for (j = 0; j < comData.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + comData.cx2_fm[j] & 0xFF); + } + + /* Copying CX2 Sense */ + for (j = 0; j < comData.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + comData.cx2_sn[j] & 0xFF); + } + + kfree(comData.ix2_fm); + kfree(comData.ix2_sn); + kfree(comData.cx2_fm); + kfree(comData.cx2_sn); + break; + + + + case CMD_READTOTMSCOMPDATA: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)totCompData.header.type); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)totCompData.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)totCompData.header.sense_node); + + /* Copying TOT CX values */ + for (j = 0; j < totCompData.node_data_size; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (totCompData.node_data[j] & + 0xFF00) >> 8, + totCompData.node_data[j] & + 0xFF); + } + + kfree(totCompData.node_data); + break; + + case CMD_READTOTSSCOMPDATA: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)totComData.header.type); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + totComData.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + totComData.header.sense_node); + + /* Copying TOT IX Force */ + for (j = 0; j < totComData.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (totComData.ix_fm[j] & + 0xFF00) >> 8, + totComData.ix_fm[j] & + 0xFF); + } + + /* Copying TOT IX Sense */ + for (j = 0; j < totComData.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (totComData.ix_sn[j] & + 0xFF00) >> 8, + totComData.ix_sn[j] & + 0xFF); + } + + /* Copying TOT CX Force */ + for (j = 0; j < totComData.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (totComData.cx_fm[j] & + 0xFF00) >> 8, + totComData.cx_fm[j] & + 0xFF); + } + + /* Copying CX2 Sense */ + for (j = 0; j < totComData.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (totComData.cx_sn[j] & + 0xFF00) >> 8, + totComData.cx_sn[j] & + 0xFF); + } + + kfree(totComData.ix_fm); + kfree(totComData.ix_sn); + kfree(totComData.cx_fm); + kfree(totComData.cx_sn); + break; + + case CMD_READSENSCOEFF: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)msCoeff.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)msCoeff.header.sense_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)ssCoeff.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)ssCoeff.header.sense_node); + + /* Copying MS Coefficients */ + for (j = 0; j < msCoeff.node_data_size; j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + msCoeff.ms_coeff[j] & 0xFF); + } + + /* Copying SS force Coefficients */ + for (j = 0; j < ssCoeff.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + ssCoeff.ss_force_coeff[j] & + 0xFF); + } + + /* Copying SS sense Coefficients */ + for (j = 0; j < ssCoeff.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + ssCoeff.ss_sense_coeff[j] & + 0xFF); + } + + kfree(msCoeff.ms_coeff); + kfree(ssCoeff.ss_force_coeff); + kfree(ssCoeff.ss_sense_coeff); + break; + + case CMD_GETFWVER: + for (j = 0; j < EXTERNAL_RELEASE_INFO_SIZE; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + systemInfo.u8_releaseInfo[j]); + } + break; + + case CMD_READCOMPDATAHEAD: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + dataHead.type); + break; + + case CMD_READ_SYNC_FRAME: + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameMS.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameMS.header.sense_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameSS.header.force_node); + + index += scnprintf(&driver_test_buff[index], + size - index, "%02X", + (u8)frameSS.header.sense_node); + + /* Copying mutual data */ + for (j = 0; j < frameMS.node_data_size; j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (frameMS.node_data[j] & + 0xFF00) >> 8, + frameMS.node_data[j] & + 0xFF); + } + + /* Copying self data Force */ + for (j = 0; j < frameSS.header.force_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (frameSS.force_data[j] & + 0xFF00) >> 8, + frameSS.force_data[j] & + 0xFF); + } + + + /* Copying self data Sense */ + for (j = 0; j < frameSS.header.sense_node; + j++) { + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X%02X", + (frameSS.sense_data[j] & + 0xFF00) >> 8, + frameSS.sense_data[j] & + 0xFF); + } + + kfree(frameMS.node_data); + kfree(frameSS.force_data); + kfree(frameSS.sense_data); + break; + + + default: + break; + } + } + + index += scnprintf(&driver_test_buff[index], + size - index, " }\n"); + limit = size - 1;/* avoid to print \0 in the shell */ + printed = 0; + } else { + /* start byte */ + driver_test_buff[index++] = MESSAGE_START_BYTE; + if (bin_output == 1) { + /* msg_size */ + driver_test_buff[index++] = (size & 0xFF00) >> 8; + driver_test_buff[index++] = (size & 0x00FF); + /* counter id */ + driver_test_buff[index++] = + (mess.counter & 0xFF00) >> 8; + driver_test_buff[index++] = (mess.counter & 0x00FF); + /* action */ + driver_test_buff[index++] = (mess.action & 0xFF00) >> 8; + driver_test_buff[index++] = (mess.action & 0x00FF); + /* error */ + driver_test_buff[index++] = (res & 0xFF00) >> 8; + driver_test_buff[index++] = (res & 0x00FF); + } else { + if (funcToTest[0] == CMD_GETLIMITSFILE_BYTE || + funcToTest[0] == CMD_GETFWFILE_BYTE) + index += scnprintf(&driver_test_buff[index], + size - index, + "%02X%02X", + (((fileSize + 3) / 4) & 0xFF00) >> 8, + ((fileSize + 3) / 4) & 0x00FF); + else + index += scnprintf(&driver_test_buff[index], + size - index, + "%02X%02X", (size & 0xFF00) >> 8, + size & 0xFF); + + index += scnprintf(&driver_test_buff[index], + size - index, "%04X", + (u16)mess.counter); + index += scnprintf(&driver_test_buff[index], + size - index, "%04X", + (u16)mess.action); + index += scnprintf(&driver_test_buff[index], + size - index, + "%02X%02X", (res & 0xFF00) >> 8, + res & 0xFF); + } + + switch (funcToTest[0]) { + case CMD_VERSION_BYTE: + case CMD_READ_BYTE: + case CMD_WRITEREAD_BYTE: + case CMD_WRITETHENWRITEREAD_BYTE: + case CMD_WRITEREADU8UX_BYTE: + case CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE: + if (bin_output == 1) { + if (mess.dummy == 1) + memcpy(&driver_test_buff[index], + &readData[1], byteToRead); + else + memcpy(&driver_test_buff[index], + readData, byteToRead); + index += byteToRead; + } else { + j = mess.dummy; + for (; j < byteToRead + mess.dummy; j++) + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + (u8)readData[j]); + } + break; + + case CMD_GETLIMITSFILE_BYTE: + case CMD_GETFWFILE_BYTE: + if (bin_output == 1) { + /* override the msg_size with dimension in words + * */ + driver_test_buff[1] = ( + ((fileSize + 3) / 4) & 0xFF00) >> 8; + driver_test_buff[2] = ( + ((fileSize + 3) / 4) & 0x00FF); + + if (readData != NULL) + memcpy(&driver_test_buff[index], + readData, fileSize); + else + pr_err("readData = NULL... returning junk data!"); + index += addr; /* in this case the byte to read + * are stored in addr because it + * is a u64 end byte need to be + * inserted at the end of the + * padded memory */ + } else { + /* snprintf(&driver_test_buff[1], 3, "%02X", + * (((fileSize + 3) / 4)&0xFF00) >> 8); */ + /* snprintf(&driver_test_buff[3], 3, "%02X", + * ((fileSize + 3) / 4)&0x00FF); */ + for (j = 0; j < fileSize; j++) + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", + (u8)readData[j]); + for (; j < addr; j++) + index += scnprintf( + &driver_test_buff[index], + size - index, + "%02X", 0); /* pad memory + * with 0x00 */ + } + break; + default: + break; + } + + index += scnprintf(&driver_test_buff[index], + size - index, "%c\n", MESSAGE_END_BYTE); + /*for(j=0; j<size; j++){ + * pr_err("%c", driver_test_buff[j]); + * }*/ + limit = size; + printed = 0; + } +ERROR: + numberParam = 0;/* need to reset the number of parameters in order to + * wait the next command, comment if you want to repeat + * the last command sent just doing a cat */ + + /* pr_err(0,"numberParameters = %d\n", numberParam); */ + + kfree(readData); + kfree(cmd); + kfree(funcToTest); + kfree(pbuf); + + fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false); + + mutex_unlock(&info->diag_cmd_lock); +exit: + return count; +} + +/** @}*/ + +/** + * file_operations struct which define the functions for the canonical + * operation on a device file node (open. read, write etc.) + */ +static struct proc_ops fts_driver_proc_ops = { + .proc_open = fts_driver_test_open, + .proc_read = fts_driver_test_read, + .proc_write = fts_driver_test_write, + .proc_lseek = fts_driver_test_lseek, + .proc_release = fts_driver_test_release +}; + +/*****************************************************************************/ + +/** + * This function is called in the probe to initialize and create the directory + * proc/fts and the driver test file node DRIVER_TEST_FILE_NODE into the /proc + * file system + * @return OK if success or an error code which specify the type of error + */ +int fts_proc_init(void) +{ + struct proc_dir_entry *entry; + + int retval = 0; + + + fts_dir = proc_mkdir_data("fts", 0777, NULL, NULL); + if (fts_dir == NULL) { /* directory creation failed */ + retval = -ENOMEM; + goto out; + } + + entry = proc_create(DRIVER_TEST_FILE_NODE, 0777, fts_dir, + &fts_driver_proc_ops); + + if (entry) + pr_info("%s: proc entry CREATED!\n", __func__); + else { + pr_err("%s: error creating proc entry!\n", __func__); + retval = -ENOMEM; + goto badfile; + } + return OK; +badfile: + remove_proc_entry("fts", NULL); +out: + return retval; +} + +/** + * Delete and Clean from the file system, all the references to the driver test + * file node + * @return OK + */ +int fts_proc_remove(void) +{ + remove_proc_entry(DRIVER_TEST_FILE_NODE, fts_dir); + remove_proc_entry("fts", NULL); + return OK; +} diff --git a/drivers/input/touchscreen/stm/i2c_fts.h b/drivers/input/touchscreen/stm/i2c_fts.h new file mode 100644 index 000000000000..e13aa8d15b00 --- /dev/null +++ b/drivers/input/touchscreen/stm/i2c_fts.h @@ -0,0 +1,89 @@ +#ifndef _LINUX_FTS_I2C_H_ +#define _LINUX_FTS_I2C_H_ + +extern struct fts_callbacks *fts_charger_callbacks; +struct fts_callbacks { + void (*inform_charger) (struct fts_callbacks *, int); +}; + +#ifdef FTS_SUPPORT_NOISE_PARAM +#define MAX_NOISE_PARAM 5 +struct fts_noise_param { + unsigned short pAddr[MAX_NOISE_PARAM]; + unsigned short pData[MAX_NOISE_PARAM]; +}; +#endif + +#ifdef FTS_SUPPORT_TOUCH_KEY +/* TSP Key Feature*/ +#define KEY_PRESS 1 +#define KEY_RELEASE 0 +#define TOUCH_KEY_NULL 0 + +/* support 2 touch keys */ +#define TOUCH_KEY_RECENT 0x01 +#define TOUCH_KEY_BACK 0x02 + +struct fts_touchkey { + unsigned int value; + unsigned int keycode; + char *name; +}; +#endif + +struct fts_i2c_platform_data { + bool factory_flatform; + bool recovery_mode; + bool support_hover; + bool support_mshover; + int max_x; + int max_y; + int max_width; + int grip_area; + int SenseChannelLength; + int ForceChannelLength; + unsigned char panel_revision; /* to identify panel info */ + + const char *firmware_name; + const char *project_name; + const char *model_name; + const char *regulator_dvdd; + const char *regulator_avdd; + + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sleep; + + int (*power)(void *data, bool on); + void (*register_cb)(void *); + void (*enable_sync)(bool on); + unsigned char (*get_ddi_type)(void); /* to indentify ddi type */ + + unsigned tspid; + unsigned tspid2; + unsigned gpio; + int vdd_gpio; + int vio_gpio; + int irq_type; + +#ifdef FTS_SUPPORT_TOUCH_KEY + bool support_mskey; + unsigned int num_touchkey; + struct fts_touchkey *touchkey; + const char *regulator_tk_led; + int (*led_power) (void *, bool); +#endif + unsigned gpio_scl; + unsigned gpio_sda; + int switch_gpio; +}; + +// #define FTS_SUPPORT_TA_MODE // DE version don't need. + +extern unsigned int lcdtype; + +void fts_charger_infom(bool en); +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +extern void trustedui_mode_on(void); +#endif +#endif |